我该怎么做才能获得聚集索引而不是聚集索引扫描?

时间:2009-08-31 21:42:03

标签: sql-server-2005 clustered-index

我在SQL Server 2005中有一个存储过程,当我运行它并查看它的执行计划时,我注意到它正在进行聚簇索引扫描,这要花费84%。我已经读过,我必须修改一些东西以获得Clustered Index Seek,但我不知道要修改什么。

我会感激任何帮助。

谢谢,

布赖恩

2 个答案:

答案 0 :(得分:20)

没有任何细节很难猜出问题是什么,甚至是否是一个问题。扫描而不是搜索的选择可以由许多因素驱动:

  • 查询表示覆盖整个表的结果集。 IE浏览器。查询是一个简单的SELECT * FROM <table>。这是一个简单的案例,可以通过一个简单的索引扫描完全覆盖,而无需考虑任何其他内容。
  • 优化器没有其他选择:
    • 查询表示整个表的子集,但过滤谓词位于不属于群集密钥的列上,并且这些列上也没有非clustred索引。除了完整扫描之外,这些都不是替代计划。
    • 该查询对clustred索引键中的列具有过滤谓词,但它们不是SARGable。过滤谓词通常需要重写以使其成为SARGable,正确的重写取决于具体情况。由于隐式转换规则,可能会出现更微妙的问题,例如。过滤谓词为WHERE column = @value但列为VARCHAR(Ascii),@ value为NVARCHAR(Unicode)。
    • 该查询对群集密钥中的列具有SARGale过滤谓词,但不会过滤最左侧的列。 IE浏览器。 clustred索引位于列(foo, bar)上,但WHERE子句仅在bar上。
  • 优化程序选择扫描。
    • 当替代品是非聚集索引然后扫描(或范围搜索)但是选择是使用聚集索引时,原因可以通常跟踪到index tipping point由于缺少查询投影的非聚集索引覆盖。请注意,这不是您的问题,因为您期望聚集索引搜索,而不是非串联索引搜索(假设问题是100%准确并记录在案......)
    • 基数估计。查询成本估计基于聚集索引关键字统计信息,该统计信息提供结果基数的估计(即,将匹配多少行)。在一个简单的查询中这不可能发生,因为任何对搜索或范围搜索的估计都将低于扫描的估计值,无论统计数据有多少,但是在复杂查询中,使用连接并且对多个表进行过滤,事情更复杂,并且计划可能包括预期搜索的扫描,因为查询优化器可以选择计划,其中连接评估顺序与观察者期望的相反。反向顺序选择可能是正确的(大多数情况下)或可能有问题(通常由于统计数据已过时或参数嗅探)。
    • 订购保证。扫描将以保证的顺序产生结果,并且执行树上更高的元素可以从该顺序中受益(例如,可以消除排序或假脱机,或者可以使用合并连接而不是散列/嵌套连接)。总的来说,由于选择明显较慢的访问路径,查询成本会更好。

这些是一些快速指针,指出在预期聚簇索引搜索时可能存在聚簇索引扫描的原因。这个问题非常通用,除了依靠8球之外,不可能回答'为什么'。现在,如果我将您的问题正确记录并正确表达,那么期望聚集索引搜索,这意味着您正在根据已确定的键值搜索唯一记录。在这种情况下,问题必须与WHERE子句的SARGability有关。

答案 1 :(得分:6)

如果Query在表中包含超过一定百分比的行,则优化器将选择执行扫描而不是搜索,因为它预测在这种情况下它将需要更少的磁盘IO(对于Seek,它返回的每一行在索引中每个级别需要一个磁盘IO,而对于扫描,整个表中每行只有一个磁盘IO。

因此,如果在b-tree索引中有5个级别,那么如果查询将生成表中超过20%的行,则读取整个表比使用每个的5个IO更便宜20%的行...

您可以稍微缩小查询的输出,以减少此过程中此步骤返回的行数吗?这将有助于它选择扫描的搜索。

相关问题