sql-server - 使用 PROBE 代替索引查找进行索引扫描

标签 sql-server tsql sql-server-2012 sql-execution-plan

我有一个如下所示的查询:

--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 组成。

这个 PROBE 在做什么,为什么我没有进行索引搜索?

更新:

Customer 表上的 FirstName 列确实有一个在 IndexSeek 中使用的索引。

CREATE NONCLUSTERED INDEX [IX_Customer_FirstName] ON Customer
(
    [FirstName] ASC
)
GO

最佳答案

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

如果您希望执行索引搜索,您需要在 CustomerId 列上指定一个新的非聚集索引。

这基本上是一个很好的做法 - 为 OrderId 和 CustomerId 设置两个单独的 NC 索引。因此,当您连接 Customer 和 CustomerOrder 表时,它将使用 NC 索引作为 CustomerId,而当您连接 Order 和 CustomerOrder 表时,它将使用 NC 索引作为 OrderId。

引用这个article阅读更多关于多列非聚集索引(您目前拥有的)和多个非聚集索引(我建议使用的)之间的区别。

[更新]

但是创建单独的非聚集索引不足以每次都进行索引查找。这将取决于在查询中选择的列,以及正在读取的数据的大小——基于此,查询优化器将相应地决定是使用 Index Seek 还是 Index Scan。参见 this answer获取更多信息。

[2021 年 2 月 8 日更新]

在较高级别,所讨论的 PROBE 函数实质上会尝试验证 CustomerOrder.OrderId 列值是否存在于 Customer 表中。这是通过使用位图和哈希键在内部实现的,您可以阅读有关它的详细信息 here .

请注意,PROBE 并非特定于索引扫描或索引查找。它只是一个函数,用于验证连接中两个表之间的匹配(基于特定的散列键列)。

关于sql-server - 使用 PROBE 代替索引查找进行索引扫描,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26164447/

相关文章:

java - Tomcat8 加载错误的 SQL Server 驱动程序/未找到 SQLServerXADataSource

c# - SQL错误: connection string does not contain the required providerName attribute

tsql - 如何在给定行周围选择 n 行

sql-server - 将SSRS中的多个值参数传递给存储过程

sql-server - 授予对 View 的读取访问权限,但不授予对其他数据库的基础表的读取访问权限

t-sql - MS SQL Server 2008/2012 获取任意两个值之间的最小差异

mysql - 根据两个表中一列的两个匹配值更新一列

c# - 使用 IN 子句更新 SQL Server 中的多行

sql - 当我在 SSMS v.17.1 中使用 "DROP TABLE IF EXISTS"时出现错误

sql-server - 子查询 T-SQL 中的 GROUP BY