在this blog post中,我需要澄清为什么SQL服务器会选择特定类型的扫描:
让我们假设为了简单 col1是独一无二的,永远都是 价值增加,col2有1000 不同的价值观和存在 表中的10,000,000行,以及 聚集索引由col1组成, 并且存在非聚集索引 COL2。
想象一下查询执行计划 最初为以下创建 传递参数:@ P1 = 1 @ P2 = 99
这些值会导致 以下是最佳查询计划 声明使用替代 参数:
从t中选择*,其中col1> 1或col2
99 by col1;
现在,想象一下查询执行计划 如果初始参数值是: @ P1 = 6,000,000,@ P2 = 550。
和以前一样,最佳查询计划会 替换之后创建 传递参数:
从t中选择*,其中col1> 6000000 或col2> 550 by col1;
这两个相同的参数化SQL 声明可能会产生 并缓存非常不同的执行 计划由于差异 最初传递参数值。 但是,由于SQL Server只缓存 每个查询一个执行计划,机会 在第一种情况下非常高 查询执行计划将使用 因为聚集索引扫描 'col1> 1'参数替换。 然而,在第二种情况下是查询 执行计划使用索引寻求 最有可能被创造。
为什么第一个查询会在第二个查询中使用聚簇索引和索引搜索?
答案 0 :(得分:1)
假设列只包含正整数:
SQL Server将查看该表的统计信息,并看到,对于第一个查询,表中的所有行都符合col1> 1的条件,因此它选择扫描聚簇索引。
对于第二个查询,相对较小比例的行将满足col1>的标准。 6000000,因此使用索引 seek 可以提高性能。
答案 1 :(得分:1)
如果优化器发现查询中将返回大部分表(例如第一个查询),则执行扫描然后执行搜索会更有效。
如果只返回表的一小部分,例如在第二个查询中,则索引搜索效率更高。
扫描会触及表格中的每一行,无论其是否合格。成本与表中的总行数成比例。如果表很小或者大多数行符合谓词的条件,则扫描是一种有效的策略。
搜索将触及符合条件的行和包含这些符合条件的行的页面,成本与符合条件的行数和页数成比例,而不是与表中的行总数成比例。< / p>
答案 2 :(得分:1)
请注意,在这两种情况下都将使用聚簇索引。在第一个例子中,它是一个聚簇索引SCAN,在第二个例子中,它将是一个聚簇索引SEEK,在大多数情况下,它会像博客作者所说的那样更快。
SQL Server知道聚集索引正在增加。因此,它将在第一种情况下进行聚簇索引扫描。