为什么SQL连接选择次优查询计划?

时间:2009-02-06 21:59:11

标签: sql sql-server

好的,所以我意识到这是一个非常含糊的问题,但请耐心等待。

我在很多场合遇到过这个问题,并且查询不同且无关。下面的查询需要很长时间才能执行:

SELECT <Fields>
FROM <Multiple Tables Joined>
    LEFT JOIN (SELECT <Fields> FROM <Multiple Tables Joined> ) ON <Condition>

但是,只需添加连接提示,它就可以在几秒钟内查询执行:

SELECT <Fields>
FROM <Multiple Tables Joined>
    LEFT HASH JOIN (SELECT <Fields> FROM <Multiple Tables Joined> ) ON <Condition>

奇怪的是,提示中指定的JOIN类型并不是真正改善性能的因素。这似乎是因为提示导致优化器单独执行子查询然后加入。如果我为子查询创建一个表值函数(不​​是内联函数),我会看到相同的性能改进。 e.g。

SELECT <Fields>
FROM <Multiple Tables Joined>
    LEFT JOIN dbo.MySubQueryFunction() ON <Condition>

任何人都有任何想法为什么优化器在这种情况下如此愚蠢?

3 个答案:

答案 0 :(得分:14)

如果这些表中的任何一个是表变量,则优化器使用0行的错误估计,并且通常选择嵌套循环作为连接技术。

这是因为缺乏有关表格的统计数据。

答案 1 :(得分:7)

优化器是一种算法。它并不愚蠢或聪明,它的工作方式与它的编程方式相同。

Hash join意味着在较小的行源上构建哈希表,这就是必须首先执行内部查询的原因。

在第一种情况下,优化器可能选择了nested loop。它将连接条件推送到内部查询中,并使用附加谓词在每次迭代时执行内部查询。它可能找不到适合此谓词的索引,并且每次迭代都会发生full table scan

除非您发布确切的查询以及表格中有多少行,否则很难说为什么会发生这种情况。

使用表函数,不可能将连接条件推送到内部查询中,这就是为什么它只被执行一次。

答案 2 :(得分:-4)

SQL Server 2005内部:T-SQL查询回答了这些问题和许多其他问题。我见过的T-SQL数据检索和动词处理的最佳外观之一。 (不,我不是这本书的作者,我也不是该书的任何作者或作者,或微软或微软出版社的附属。这只是一项令人难以置信的工作,而且我已经转向了过去的各种DBA几年同意。)