类似查询的不同执行计划

时间:2010-06-08 14:27:12

标签: sql sql-server-2005 sql-execution-plan

我正在运行两个非常相似的更新查询,但由于我不知道的原因,他们使用完全不同的执行计划。通常这不会是一个问题,但它们都在更新完全相同的行数,但是一个使用的执行计划远远低于另一个,4秒vs 2分钟,当按比例放大时这会导致一个大问题

两个查询之间的唯一区别是使用列CLI和另一个DLI。这些列的数据类型完全相同,并且索引完全相同,但对于DLI查询执行计划,不使用索引。

非常感谢任何有关为何发生这种情况的帮助。

-- Query 1
UPDATE a
 SET DestKey = ( 
 SELECT TOP 1 b.PrefixKey 
 FROM refPrefixDetail AS b 
 WHERE a.DLI LIKE b.Prefix + '%' 
 ORDER BY len(b.Prefix) DESC )
FROM CallData AS a

-- Query 2
UPDATE a
 SET DestKey = ( 
 SELECT TOP 1 b.PrefixKey 
 FROM refPrefixDetail b 
 WHERE a.CLI LIKE b.Prefix + '%' 
 ORDER BY len(b.Prefix) DESC )
FROM CallData AS a

2 个答案:

答案 0 :(得分:3)

检查表中这两列的统计信息(列的数据值如何在所有行之间分配)。这可能会解释差异......这些列中的一个可能具有值的分布,这些值可能导致查询在处理过程中需要检查比其他查询所需的行数更多的行(数字)或更新的行由前1部分控制记住)然后查询优化器可能会选择不使用索引...更新统计信息将使它们更准确,但如果值的分布是优化程序选择的不要使用索引,那么你可能会运气不好......

了解指数的工作原理在这里很有用。索引是节点的树结构,其中每个节点(以根节点开始)包含允许查询处理器基于其“搜索”的值确定树的哪个分支接下来的信息。它类似于二叉树,除了在数据库中树不是二进制树,在每个级别,每个节点下面可能有多于2个分支。

因此,对于索引,要遍历索引,从根到叶级别,要求处理器为索引层次结构中的每个级别读取索引一次。 (例如,如果索引深度为5级,则需要为其搜索的每条记录执行5次I / O操作。

所以在这个例子中,比如说,如果查询需要检查表中超过大约20%的记录(基于您要搜索的列的值分布),那么查询优化器会说本身,“自我,找到20%的记录,每个记录搜索有5个I / O,等于读取整个表的I / O数量相同。”,所以它只是忽略了索引并且做了表扫描。

除了通过在查询中添加附加条件以限制查询必须检查的记录数以生成结果之外,真的没有办法避免这种情况....

答案 1 :(得分:1)

尝试更新统计信息。如果这无助于尝试重建索引。每列中数据的基数可能完全不同,从而导致选择不同的执行计划。