Ale*_*min 16 performance sql-server optimization t-sql performance-tuning
我有一个查询,它连接了几个表并且执行得非常糟糕 - 行估计偏离了(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
Run Code Online (Sandbox Code Playgroud)
玩弄查询时,我注意到当我提示它对其中一个连接使用合并连接时,它的运行速度要快很多倍。这我可以理解 - 合并连接是连接数据的更好选择,但 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。
Pau*_*ite 22
通过阅读不同的文章和书籍,我假设基数估计是在制定计划之前进行的。
不完全是。一个初始基数估计导出,从而影响由所述优化器选择的初始连接顺序(简化和其他工作之后)。
但是,后续探索(在基于成本的优化期间)可以并且经常会导致计算新的基数估计。这些后来的 CE 可能或多或少“准确”。如果低估结果,优化器可能会选择一个看起来更便宜但实际上运行时间更长的计划。
一般来说,不能保证语义相同的子树的基数估计会产生相同的结果。毕竟是一个统计过程,有些操作比其他操作有更深的CE支持。
在您的情况下,似乎还有另一个因素 - 优化器引入(或移动)一个 Top,它在它下面的子树上设置了一个行目标:
如果您要启用跟踪标志 4138(在 2008 R2 或更高版本上),您可能会发现估计更符合预期,或者甚至优化器将不再选择嵌套循环。
然而,我看到的是合并提示使所有估计变得非常完美。
这里有运气的成分。人们倾向于按照他们期望在物理上执行的顺序编写查询,或者至少是连接。使用连接提示带有一个隐含的FORCE ORDER,从而固定连接顺序以匹配文本形式,并关闭许多可能导致基数重新估计的优化器探索规则。
除此之外,我尝试运行查询
OPTION (FORCE ORDER)- 它比使用合并联接运行得更快,为每个联接选择 HASH MATCH。
这与暗示连接相同,但不限制物理连接运算符的选择。同样,如果您碰巧以合乎逻辑的方式编写查询连接顺序,您很可能会得到一个合理的计划。当然,您会以这种方式错过优化器的大部分功能,这在更一般的情况下可能无法产生最佳结果。
您可能不想FORCE ORDER经常使用,因为它是一个非常强大的提示(指令),它比简单地强制连接顺序具有更广泛的效果;例如,它可以防止优化器四处移动聚合并引入部分聚合。我非常建议不要使用这个提示,除非在非常特殊的情况下,并且由真正的专业调音师使用。
详细的分析需要比我现在更多的时间,并且需要访问仅用于统计的数据库副本。
| 归档时间: |
|
| 查看次数: |
584 次 |
| 最近记录: |