【问题标题】:Execution plan shows index seek for 'is null' query on non-clustered index执行计划显示对非聚集索引的“is null”查询的索引搜索
【发布时间】:2016-01-29 17:25:41
【问题描述】:

据我所知,具有空值的列上的索引在“为空”查询中无济于事,因为空匹配所有内容。所以我期待在执行计划中看到索引扫描或全表扫描。

但是,当我查看查询的实际执行计划时,我发现它正在执行 Index Seek。

这怎么可能?还是红鲱鱼?

【问题讨论】:

  • 我不确定您所说的“Null 匹配所有内容”是什么意思 - 但我不知道寻找 null 不起作用的原因.. 我可能错了 - 你在哪里获取此信息?
  • 这是一个公平的问题,为什么被否决
  • 好吧,可能是因为它在特殊情况下声明了特殊的预期行为,而没有说明预期行为的原因。我投票决定关闭,因为没有更多信息,答案似乎是“您对预期的结果有误解”。
  • @Blorgbeard,你似乎是 sql 和英语方面的专家,我都不是。回答某人的问题比对问题本身挑剔要好,你能回答1. sql server 是否索引空值? 2. 如果你的回答是否定的,那么你能解释一下我的查询是如何在索引搜索中结束的吗?
  • @Ranjan 你可以在下面看到我的答案

标签: sql-server sql-server-2008-r2


【解决方案1】:

我理解您的问题,您担心为什么查询优化器在所有行只有 NUll 数据时选择索引搜索,它应该进行索引扫描或全表扫描,因为它最终读取所有行而不是我的可空列。 这怎么可能?还是红鲱鱼?

首先, 看一下NONCLUSTERD INDEX SEEK ON TOOLTIP"的定义

在非聚集索引上扫描特定范围的行

"

Seek 并不总是通过 b-tree 结构进行搜索,有时它是一个搜索范围 所以实际上你可以说在 sql server 中有两种类型的 seek

(1) Singleton Lookups : 只有当它直接通过 B-tree 时 根到叶以获得精确匹配的行,并且仅在唯一的情况下发生 具有 euality 谓词的索引。

(2) SEEK PLUS Range Scans : 当它通过 B-tree 根到叶子时 然后在一个方向上通过另一片叶子执行范围扫描 直到它限定匹配的行。

所以在您的情况下,它实际上是一个 SEEK PLUS 范围扫描,其中索引中的所有行都对数据进行了限定。

那么为什么它没有进行全表扫描?

因为您使用的是谓词“SomeIO 为空”
someid 有非唯一的非聚集索引 并且 INDEX 页面大小比 table/custered INDEX 的页面大小更小,因此阅读更少的页面总是更好。

那么为什么它没有做full INDEX SCAN 为什么选择INDEX SEEK?

为此,我将通过查找和扫描同一查询向您展示执行计划

你可能知道 Sql server 创建多个逻辑表达查询的物理计划, 并选择总成本最低的查询计划。 因此您可以在上图中看到,使用索引查找的查询计划的总体成本低于索引扫描(其中一个原因是上述计划中的成本较低是估计的行大小)。 在现实世界中,您可以比较两者。

在我的系统上,我的 TestTable 的页面读取和扫描计数相同

扫描计数 1,逻辑读取 3179,

热切结果:

基线是 5 次执行不平行

  ITERATOR      max time   min time    avg time
 INDEX SEEK     122 ms.    112 ms.     116 ms
 INDEX SCAN     149 ms     139 ms      145 Ms

在我的系统上,Seek 也获胜。

现在完全不同的问题是这个指标是否值得。

在 OP 评论之后。 sql server 是否索引空值?

是的...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-15
    • 1970-01-01
    • 2014-08-27
    • 2011-01-22
    • 2013-08-07
    • 2014-07-28
    • 1970-01-01
    相关资源
    最近更新 更多