sha*_*non 10 performance sql-server-2008 sql-server optimization hints query-performance
我有一个有点复杂的 SQL Server 2008 查询(大约 200 行相当密集的 SQL),它没有按照我的需要执行。随着时间的推移,性能从大约 0.5 秒下降到大约 2 秒。
查看执行计划,很明显,通过重新排序连接,可以提高性能。我做到了,它做到了……下降到大约 0.3 秒。现在查询有“OPTION FORCE ORDER”提示,生活很好。
今天我来了,清理数据库。我归档了大约 20% 的行,除了删除行之外,在相关数据库中没有采取任何行动……执行计划完全被控制。它完全错误地判断了某些子树将返回多少行,并且(例如)替换了一个:
<Hash>
Run Code Online (Sandbox Code Playgroud)
和
<NestedLoops Optimized='false' WithUnorderedPrefetch='true'>
Run Code Online (Sandbox Code Playgroud)
现在查询时间从大约 0.3 秒飙升到大约 18 秒。(!) 只是因为我删除了行。如果我删除查询提示,我将回到大约 2 秒的查询时间。更好,但更糟。
将数据库恢复到多个位置和服务器后,我重现了该问题。简单地从每个表中删除大约 20% 的行总是会导致这个问题。
如果您想查看执行计划,请建议我可以发布它们的位置。否则,我已经采样了最令人惊叹的一点。这是基本的错误估计,括号中的数字是(估计:实际)行。
/ Clustered Index Scan (908:7229)
Nested Loops (Inner Join) --<
\ NonClustered Index Seek (1:7229)
Run Code Online (Sandbox Code Playgroud)
请注意,内循环预期扫描 908 行,但扫描 52,258,441。如果它是准确的,这个分支会运行大约 2 毫秒,而不是 12 秒。在删除行之前,这个内部连接估计值仅相差 2 倍,并且作为两个聚集索引的哈希匹配执行。
对于强制连接顺序使查询估计完全不准确(因此查询时间不可预测),这是否正常?
FORCE ORDER 的使用不会使估计不准确,行的删除确实如此。强制更新表上的统计信息可能会提高估计的准确性。
我应该只是期望我要么接受次优查询性能,要么像鹰一样观察它并经常手动编辑查询提示?或者也提示每个加入?.3s 到 2s 是一个很大的打击。
最好是确保优化器获得生成最佳计划所需的信息,而不使用 FORCE ORDER 提示。通过这样做,它应该更好地应对底层数据分布的变化,而无需人工干预。也就是说,如果数据的性质使得基数可能逐小时或逐小时显着变化,请考虑使用计划指南来确保计划是固定的。
为什么优化器在删除行后爆炸很明显?例如,“是的,它进行了样本扫描,并且由于我在数据历史记录中较早地存档了大部分行,样本产生了稀疏结果,因此它低估了对排序散列操作的需求”?
您没有提到问题表中的行数,但删除很可能是:
您也可能会遇到老式的参数嗅探问题,对此有无数的选择可以解决。WITH RECOMPILE可能是使用如此大的查询指定的昂贵选项,但在过程和语句级别都值得研究。
归档时间: |
|
查看次数: |
15887 次 |
最近记录: |