我有一个查询,该查询连接了几个表并且执行得很差-行估计相差1000倍,并且选择了嵌套循环连接,从而导致了多个表扫描。查询的形状非常简单,看起来像这样:
SELECT t1.id
FROM t1
INNER JOIN t2 ON t1.id = t2.t1_id
LEFT OUTER JOIN t3 ON t2.id = t3.t2_id
LEFT OUTER JOIN t4 ON t3.t4_id = t4.id
WHERE t4.id = some_GUID
在处理查询时,我注意到当我提示它对一个连接使用合并连接时,它的运行速度快了很多倍。我能理解-合并联接是联接数据的更好选择,但是SQL Server选择嵌套循环时并不能正确估计它。
我不完全理解的是,为什么此联接提示会更改所有计划运营商的所有估计?通过阅读不同的文章和书籍,我假设基数估计是在构建计划之前执行的,因此使用提示不会改变估计,而是明确地告诉SQL Server使用特定的物理联接实现。
但是,我看到的是,合并提示使所有估计变得非常完美。为什么会发生这种情况,并且有任何通用的技术可以使查询优化器在没有提示的情况下做出更好的估计-考虑到统计数据显然可以做到这一点?
UPD:可在此处找到匿名的执行计划:https ://www.dropbox.com/s/hchfuru35qqj89s/merge_join.sqlplan?dl =0 https://www.dropbox.com/s/38sjtv0t7vjjfdp/no_hints_join.sqlplan?dl = 0
我使用TF 3604、9292和9204检查了两个查询使用的统计信息,它们是相同的。但是,查询之间扫描/查找的索引有所不同。
除此之外,我尝试使用来运行查询OPTION (FORCE ORDER)
-它的运行速度比使用合并连接还要快,为每个连接选择HASH MATCH。