我有一个看起来像这样的查询:
--Updated To remove Distinct per Aaron Bertrand's suggestion in the comments
SELECT TOP 100 ord.OrderId
FROM Customer cust
JOIN CustomerOrder ord
ON ord.CustomerId = cust.CustomerId
WHERE cust.FirstName LIKE (@firstName + '%')
ORDER BY ord.CreatedWhen DESC
而且我有这样的索引:
CREATE NONCLUSTERED INDEX [IX_MyIndex] ON CustomerOrder
(
OrderId DESC,
CustomerId DESC,
CreatedWhen Desc
)
GO
当我运行查询时,将使用索引,但这是索引扫描。它给出了此消息:
PROBE([Bitmap1011],[MyDatabase]。[order]。[CustomerOrder]。[OrderId] as [ord]。[OrderId],N'[IN ROW]')
输出列表由OrderId和CreatedWhen组成。
这个探针在做什么,为什么我没有索引搜寻?
更新:
Customer表上的FirstName列的确具有在IndexSeek中使用的索引。
CREATE NONCLUSTERED INDEX [IX_Customer_FirstName] ON Customer
(
[FirstName] ASC
)
GO
使用索引扫描的原因是因为您的WHERE子句谓词基于CustomerId,但它在非聚集索引[IX_MyIndex]的列列表中显示为SECOND列。
如果要执行索引Seek,则只需要在CustomerId列上指定一个新的非聚集索引。
这本质上是一个好习惯-为OrderId和CustomerId有两个单独的NC索引。因此,当您联接Customer和CustomerOrder表时,它将使用NC索引作为CustomerId,而当您联接Order和CustomerOrder表时,它将使用NC索引作为OrderId。
请参阅此article,以了解有关多列非聚集索引(您当前拥有的)和多个非聚集索引(我建议使用的)之间的区别的更多信息。
[UPDATE]
但是创建单独的非聚集索引不足以每次都获得索引查找。这将取决于查询中选择的列以及要读取的数据的大小-基于此,查询优化器将相应地决定是使用索引查找还是索引扫描。有关更多信息,请参见this answer。
简单原因:FirstName
列不在索引中。它必须扫描每一行以查看该行是否与所需的模式匹配。