我正在创建下表
CREATE TABLE dbo.COMM_SHELF_BLOCK_ACCESS
(
KeyId uniqueidentifier NOT NULL ROWGUIDCOL CONSTRAINT DF_COMM_SHELF_BLOCK_ACCESS_KeyId default NEWSEQUENTIALID(),
EmployeeGuid uniqueidentifier NOT NULL,
PracticeVid smallint NOT NULL,
ShelfGuid uniqueidentifier NOT NULL,
CONSTRAINT PK_COMM_SHELF_BLOCK_ACCESS PRIMARY KEY CLUSTERED (KeyId)
) ON [PRIMARY]
GO
CREATE UNIQUE NONCLUSTERED INDEX UX_COMM_SHELF_BLOCK_ACCESS
ON dbo.COMM_SHELF_BLOCK_ACCESS (ShelfGuid, EmployeeGuid, PracticeVid)
GO
我从不KeyId
在我的程序中使用它,它仅用于合并复制。我的应用程序将使用此表的最常见查询是
--This will be passed in parameters to the SP
declare @practiceVid smallint = 0
declare @employeeGuid uniqueidentifier = 'C413A410-E13E-4647-9D68-2A38FBC45906'
--actual query
select * from COMM_SHELF
where COMM_SHELF.SHELF_GUID not in
(
select ShelfGuid
from COMM_SHELF_BLOCK_ACCESS
where EmployeeGuid = @employeeGuid
and PracticeVid = @practiceVid
)
我的新表的索引结构是否合适?在我看来最重要的是我正在复制那个唯一索引中的几乎整个表。我做的另一个想法是像下面这样构造表格
CREATE TABLE dbo.COMM_SHELF_BLOCK_ACCESS
(
KeyId uniqueidentifier NOT NULL ROWGUIDCOL CONSTRAINT DF_COMM_SHELF_BLOCK_ACCESS_KeyId default NEWSEQUENTIALID(),
EmployeeGuid uniqueidentifier NOT NULL,
PracticeVid smallint NOT NULL,
ShelfGuid uniqueidentifier NOT NULL,
CONSTRAINT PK_COMM_SHELF_BLOCK_ACCESS PRIMARY KEY NONCLUSTERED (KeyId),
CONSTRAINT CK_COMM_SHELF_BLOCK_ACCESS UNIQUE CLUSTERED (ShelfGuid, EmployeeGuid, PracticeVid)
) ON [PRIMARY]
GO
使这 3 列成为我对聚集键感兴趣的列。然而,这违反了我到处阅读的“保持聚簇键窄”和“保持聚簇键顺序”指南。
这些方法中的哪一个是实现它的正确方法?如果两者都不正确,请告诉我处理此问题的正确方法是什么。
“保持聚簇键顺序”建议的主要原因是围绕插入/更新/删除操作和碎片。当您对值进行更改时(无序插入新值、更新导致其移动的旧值、删除值)SQL 必须在页面上四处移动数据并进行页面拆分以保持数据有序(聚簇索引的全部目的)。这将需要时间并产生碎片化,这将随着时间的推移减慢一切。
如果您只进行很少的更新(包括插入/删除)或每次更新完成时都重建您的表(截断然后批量加载),那么对于自然顺序不正确的值的聚簇索引可以为您工作。否则坚持你的顺序值。
就您的索引而言,仅基于那个查询,我更喜欢这个:
您不希望 ShelfGuid 在前面,因为它必须进行索引扫描才能找到它想要的 EmployeeGuid。如果您实际上并不打算在 ShelfGuid 上进行搜索,而只想返回该值,则将其完全从索引的树级别中取出,然后将其放入叶级别(通过包含它)。
如果您有索引的空间(我猜您有),那么不用担心它几乎与桌子一样大。它仍然是一个按特定顺序对数据进行排序的索引。我猜您的目标是加快查询速度而不是节省空间。如果您的空间紧张并且负担不起更多,那么您会遇到不同的问题,我会考虑使用 GUID 以外的东西重做您的表格 :)。