2010-06-08 39 views
1

我正在运行两个非常相似的更新查询,但由于我未知的原因,他们正在使用完全不同的执行计划。通常这不会是一个问题,但他们都更新完全相同数量的行,但一个正在使用的执行计划,远远低于其他,4秒比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 

回答

3

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

了解索引如何工作在这里很有用。索引是节点的树状结构,其中每个节点(从根节点开始)包含的信息允许查询处理器根据它正在“搜索”的值来确定要去哪个树的哪个分支。它类似于二叉树,只是在数据库中树不是二进制的,在每个层次上,每个节点下可能有多于2个分支。

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

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

除了通过添加附加条件到您的查询以进一步限制查询必须检查的记录数以生成结果....

+0

感谢您的及时响应 我已经检查了这两个指标的统计数据,我不确定我在这里寻找什么,有什么建议吗?有一些不同之处。有什么我可以做的例如,有没有什么办法可以强制优化器使用索引,因为它似乎正在采用的路线的效率要低得多。如果索引不能改进我的查询,似乎毫无意义的索引 – 2010-06-08 15:18:14

+0

了解索引如何工作在这里是有用的。我正在编辑我的答案添加此.... – 2010-06-08 15:57:17

+0

感谢您的解释,这当然帮助我理解为什么会发生这种情况。不幸的是,我无法进一步限制结果,所以我想我必须忍受这一点,因为从你所说的事实上来看,它实际上是最有效的方式。 – 2010-06-09 13:42:32

1

尝试更新您的统计信息。如果这没有帮助重建索引。每列中数据的基数可能很不相同,从而导致选择不同的执行计划。

+0

我已删除我的索引并重新创建,我已重建索引,更新统计信息并截断并重新插入数据。这些都不会对查询执行计划产生任何影响。 :-( – 2010-06-08 15:19:24

相关问题