为什么我的ORDER BY在EXCEPT(慢)之前而不是在(快)之后对两个表排序?


12

SQL Server 2008 R2查询优化器难题

我们有两个表,每个表都包含900万行。70.000行不同,其他相同。

快13秒

select * from bigtable1
except select * from similar_bigtable2

这样可以对输出进行排序,而且速度也很快(13秒),

select * into #q from bigtable1
except select * from similar_bigtable2
select * from #q order by sort_column

尽管这非常慢:

;with q as (
    select * from bigtable1
    except select * from similar_bigtable2
)
select * from q order by sort_column

甚至是我有时用来提示SQL Server的“技巧”,它都需要在继续进行之前预先计算查询的某个部分,它不起作用,并且也会导致查询速度变慢:

;with q as (
    select top 100 percent * from bigtable1
    except select * from similar_bigtable2
)
select * from q order by sort_column

查看查询计划的原因并不难发现:

查询计划 用ORDER BY查询计划

SQL Server 在哈希匹配之前放置两种900万行,而我希望它在哈希匹配之后仅添加一种70.000行。

那么问题来了:我如何指示查询优化器执行此操作?


3
它不会在哈希匹配之前进行排序,而是先进行排序然后进行合并联接(而不是哈希联接)。也许有一个提示可以强制执行哈希联接(或阻止合并联接)?
Thilo 2012年

3
似乎SQL Server查询优化器确定对数据进行排序是有好处的,因此它可以使用快得多的合并联接(仅适用于排序的数据),而不是慢得多的哈希匹配联接或嵌套循环联接....
marc_s

9
您是否尝试过替代EXCEPT(例如OUTER JOIN)的方法?我意识到语法不太方便,但是您可以在那里更好地使用索引/联接提示(或者您可能不需要)。您现在正在使用的替代方法(首先填充到#temp表中)是最后的解决方法,但在某些情况下,这是强制优化器以所需方式将查询的两个部分完全分开的唯一方法。
亚伦·伯特兰

Answers:


1

这两个查询计划之间的主要区别实际上是哈希匹配和合并联接的区别。哈希匹配效率更高,并且您可以看到查询在选项1中运行得更快(不使用CTE)。

CTE是一个很棒的工具,但是在两种情况下(复杂谓词或非唯一父/子键)似乎效率不高。在您的情况下,没有唯一键,并且SQL Server必须首先对数据集进行排序才能满足您的要求。请看下面的链接,它告诉您有关此问题的更多信息:http : //blogs.msdn.com/b/sqlcat/archive/2011/04/28/optimize-recursive-cte-query.aspx

因此,看来您要么必须接受它的缓慢性,要么用WHILE循环重写该逻辑可以更有效。


0

试试这个,更好吗?

select * from
(
    select * from bigtable1
    except 
    select * from similar_bigtable2
) t
order by sort_column

0

这不是理想的解决方案,但是如果您无法构造tsql以生成有效的计划,则可以设置计划指南以强制执行所需的计划。这样做将意味着,如果有更有效的计划可用,SQL将不会考虑它,但这是一个选择。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.