使用PROBE而不是寻求索引的索引扫描

问题描述 投票:2回答:2

我有一个看起来像这样的查询:

--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
sql-server tsql sql-server-2012 sql-execution-plan
2个回答
1
投票

使用索引扫描的原因是因为您的WHERE子句谓词基于CustomerId,但它在非聚集索引[IX_MyIndex]的列列表中显示为SECOND列。

如果要执行索引Seek,则只需要在CustomerId列上指定一个新的非聚集索引。

这本质上是一个好习惯-为OrderId和CustomerId有两个单独的NC索引。因此,当您联接Customer和CustomerOrder表时,它将使用NC索引作为CustomerId,而当您联接Order和CustomerOrder表时,它将使用NC索引作为OrderId。

请参阅此article,以了解有关多列非聚集索引(您当前拥有的)和多个非聚集索引(我建议使用的)之间的区别的更多信息。

[UPDATE]

但是创建单独的非聚集索引不足以每次都获得索引查找。这将取决于查询中选择的列以及要读取的数据的大小-基于此,查询优化器将相应地决定是使用索引查找还是索引扫描。有关更多信息,请参见this answer


0
投票

简单原因:FirstName列不在索引中。它必须扫描每一行以查看该行是否与所需的模式匹配。

© www.soinside.com 2019 - 2024. All rights reserved.