我想我已经找到了答案,但我希望能得到一些额外的观点。
假设我们将JOIN
两个表放在一个共享列上,然后每个表都有一个不同的表,column
我们将对其进行Constant
搜索。当我们构建一个index
支持查询的时候,对于每个表,我们是想把JOIN
ing放在第column
一个还是第Constant
column
一个?我现在想这是第Constant
column
一个。当我查看提示此问题的不同查询的查询计划时,它似乎尝试创建每个表的子集,然后将JOIN
它们一起创建。而不是JOIN
将两个表放在一起并从那里过滤。
EX:在发货且客户处于活动状态的情况下将发货加入客户
SELECT [Columns]
FROM Shipment S
INNER JOIN Customer C
ON S.CustomerID = C.CustomerID
WHERE S.IsShipped = 1
AND C.IsActive = 1
我认为要使用的两个最佳索引如下。因为Query Optimizer
他们宁愿先扫描第一个,Constant
然后再扫描JOIN
第二个column
,而不是JOIN
将两者tables
放在一起,然后再过滤constant
。
CREATE NONCLUSTERED INDEX [IX_IsActive-CustomerID] ON [dbo].[Customer]
(
[IsActive] ASC,
[CustomerID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_IsShipped-CustomerID] ON [dbo].[Shipment]
(
[IsShipped] ASC,
[CustomerID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
代替:
CREATE NONCLUSTERED INDEX [IX_CustomerID-IsActive] ON [dbo].[Customer]
(
[CustomerID] ASC,
[IsActive] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [IX_CustomerID-IsShipped] ON [dbo].[Shipment]
(
[CustomerID] ASC,
[IsShipped] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
那正确吗?
假设没有其他需要关注的查询,一般的答案是您希望在索引的前导列中有更多选择性标准(请注意,这里的选择性与谓词有关,而不是衡量列中特定值的唯一性是)。通常,您希望优化器尽快消除尽可能多的行。
假设
CustomerID
inShipment
isNOT NULL
和 有一个外键Customer
,这意味着inner join
保证不会从 中删除任何行Supplier
,那么s.IsShipped = 1
它是唯一的选择性谓词,它作为前导列是有意义的。另一方面,如果inner join
更具选择性(假设有人定期将行从 移动Customer
到并可以加入其中任何一个表),那么将其作为前导列是有意义的。Customer_Archive
Shipment
CustomerID