我有一个之前执行缓慢的查询。后来我发现它没有并行运行,这使得查询执行速度变慢。
查询涉及一个 big view
,然后用很多 和 查询temp tables
视图sub query
。
我UDF
从视图中删除了一个并inline functions
使用了一个标量TVF
,然后它开始在parallel execution
.
这几天进展顺利,有一天我注意到查询运行缓慢。于是查看了执行计划,发现查询是串行模式执行的。我检查了查询的计划缓存,我看到了很多涉及该视图的缓存计划。我删除了不并行的计划,然后查询运行得很快。
现在我每天早上都这样做以强制查询并行运行。
额外细节:
- SQL Server 2016 标准版
- 查询通过 LINQ-SQL 从 dot net 应用程序生成。所以临时查询。
如何强制查询永远并行运行?
乍一看,这听起来像是一个经典的参数嗅探问题。
SQL Server 为需要编译计划时调用的第一组参数构建执行计划,然后在一天中反复使用该计划。您可以看到它们是什么参数 - 当您查看序列计划时,右键单击选择语句,然后进入属性。在属性窗口中,查找 Parameters,然后查找 Compiled Values。这将向您显示哪些值生成序列计划。
为了强制计划始终并行运行,您有几种不同的选择(Erland 在我上面链接的他的优秀帖子中介绍了其中的许多选项),包括:
这只是一个快速的回答——但要了解更多,请阅读Erland 的优秀文章,应用程序慢,SSMS 快,它解释了一个查询如何获得不同的计划,以及如何修复它。
可能很难为您的问题提供准确的答案,因为我们不知道您的查询是什么样的,但是您可以使用 SQL 2016 中引入的 QueryStore 功能强制执行特定计划。如果您使用的是早期版本SQL Server 或不认为查询存储是适合您的解决方案 - 您可以尝试以下方法:
您还应该查看 StackExchange 上关于此主题的先前帖子,例如SQL not engaging parallelism for extremely large query
如果查询的成本超过该
Cost Threshold of Parallelism
值且cost of the parallel plan
小于cost of a serial plan
,则将创建并使用并行计划。在某些情况下,QO 选择串行计划而不是并行计划,因为
parallel plan
它比那种情况更昂贵serial plan
。例如,如果查询包含无法在并行模式下运行的标量或关系运算符。在某些情况下,由于信息不准确、统计数据过时、质量差等原因,QO 会做出错误的决定
cardinality estimate
。因此,串行计划的成本略高于parallel plan
。所以QO还是选择serial plan。
为了克服这个问题,可以优化查询并且还应该更新统计信息。
这有助于 QO 做出正确的决定。
这些都是受欢迎的步骤,只要您改进了查询,一些计划就会并行执行,查询性能也会得到提高。
因此,可能还有进一步改进查询的范围。
人们应该更多地关注优化查询和调整索引而不是直接尝试
Hint
其余的事情,比如使用提示、参数嗅探、选项(重新编译)已经讨论过了。