【问题标题】:Index seek changes to index scan on change of value in where clause在 where 子句中的值变化时,索引寻求对索引扫描的更改
【发布时间】:2017-02-20 21:11:04
【问题描述】:

我有一个表 ORDER 有 64 列,OrderNo 是主键。它还有两列ParentOrderNoType。对于单独的订单,Type 和 ParentOrderNo 将为 NULL,对于分组订单,Type 将填充“PRNT”或“CHLD”。 OrderNo where Type='PRNT' 将填充到其组中所有订单(PRNT 和 CHLD)的 ParentOrderNo 列。一组可以有 1 个父订单和 2 个或更多子订单。该表具有用于列 ParentOrderNoType 的非聚集索引 (IX_ORDER_1)。

此表共有 31654 行。在我的测试用例中,有 30001 个订单(1 个父级和 30000 个子级)。

当我执行查询时:

Select top 1 *
  From   ORDER                  
  where PARENTORDERNO = '11278'  and Type ='prnt'

执行计划显示 Index Seek 使用 (IX_ORDER_1)

但是当我执行查询时:

Select top 1 *
  From   ORDER                  
  where PARENTORDERNO = '11278'  and Type ='chld'

执行计划显示Index Scan using clustered index

有人可以指导我是什么导致执行计划发生这种变化。 提前致谢

【问题讨论】:

    标签: sql sql-server


    【解决方案1】:

    根据数据库维护的有关索引的统计信息,优化器(正确地)估计在type='parent' 时匹配条件的记录很少,因此查找效率更高。对于type='child',它估计有足够的记录,扫描会更有效,因为它将返回表中的大部分内容,而不是只返回一条记录。

    在执行计划中,查看两个不同运行的Estimated Rows(和Actual Rows,以了解估计的准确度)。

    【讨论】:

    • 扫描何时比搜索更有效?以及如何?
    【解决方案2】:

    很遗憾我无法添加评论,所以我这样回答:

    您何时从表中选择超过 cca 15% 的行(百分比因来源而异,但通常它们坚持 10 到 15%),执行计划很可能会使用索引扫描而不是索引搜索。

    在你的情况下,如果我理解正确,你有

    " 在我的测试用例中,有 30001 个订单(1 个父级和 30000 个子级)。"

    只有一个父行,这是索引搜索的好候选者,以及 30 000 个子行,这对于查询优化器来说绝对是不好的候选者。

    【讨论】:

    • 你的回答很有用。我点击了“这个答案很有用”按钮。但是我收到了这条消息“感谢您的反馈!声望低于 15 人的投票将被记录,但不要更改公开显示的帖子分数”。感谢帮助。我现在的声望是6。 :(
    猜你喜欢
    • 2017-05-16
    • 2015-01-26
    • 1970-01-01
    • 2019-06-10
    • 2011-06-28
    • 2015-01-24
    • 2019-08-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多