seb*_*eid 7 sql-server execution-plan sql-server-2016 memory-grant
我有一个带有多个执行计划的查询,与第二个计划相比,授予一个计划的内存是巨大的
当嵌套循环联接的外部表具有将结果过滤为小输入的谓词时,会出现问题,但批处理排序似乎使用与整个外部表等效的基数估计值。这可能会导致感知到过多的内存授予,这在非常并发的服务器中可能会产生多种副作用,例如 OOM 条件、计划缓存驱逐的内存压力或意外的 RESOURCE_SEMAPHORE 等待。我们已经看到,匹配此模式的单个查询实际上可以在高端机器(1TB+ RAM)上获得几 GB 的授予内存。
到目前为止,一种选择是使用跟踪标志 2340 全局禁用此功能,如 KB 2801413 中所述。但是,在 SQL Server 2016 RC0 中,我们已更改行为以保持优化的优势,但现在最大授予限制基于在可用的内存授予空间上。这种改进也转化为更好的可扩展性,从某种意义上说,可以用更小的内存占用执行更多的查询。我们正在考虑将此行为反向移植到即将推出的已将此行为移植到 SQL Server 2014 Service Pack 2,并像往常一样为市场上的版本提供附加值。
这正是我所看到的,但是我使用的是 SQL Server 2016 Enterprise。
这些是执行计划
https://www.brentozar.com/pastetheplan/?id=SJ0mYAy0b
https://www.brentozar.com/pastetheplan/?id=BJzutC1R-
我的问题是
2个执行计划的原因是什么?
优化器正在使用顶部执行计划,我强迫它使用较低的计划,但过了一段时间它又回到顶部执行计划,有什么原因吗?
如何解决这个问题?这个问题导致应用程序崩溃(有很多RESOURCE_SEMAPHORE
等待,应用程序变得无响应)?我应该使用提示:DISABLE_OPTIMIZED_NESTED_LOOP
还是 Trace Flag 2340
?
注意:我检查了 XML,两个计划都有 NestedLoops Optimized="false"
1. 2个执行计划的原因是什么?
来自sys.query_context_settings (Transact-SQL)文档:
SQL Server 中有许多可用的上下文设置会影响查询语义(定义查询的正确结果)。在不同设置下编译的相同查询文本可能会产生不同的结果(取决于底层数据)。
似乎很可能相同的查询文本是从具有不同上下文设置的会话中提交的。另请参阅在应用程序中慢,在 SSMS 中快?作者:厄兰·索马斯科格。
2.优化器正在使用顶级执行计划,我强迫它使用较低的计划,但过了一段时间它又回到了顶部,这是什么原因?
计划仍会不时根据围绕更改的正常规则重新编译,例如底层对象、统计信息、模式。正如sys.query_store_plan (Transact-SQL) 所指出的,强制执行查询存储计划有助于确保所使用的计划至少在根本上与源计划相似:
强制机制不保证该计划将用于query_id引用的查询。计划强制会导致再次编译查询,并且通常会生成与plan_id引用的计划完全相同或相似的计划。
每个(重新)编译可能会生成具有不同估计(包括内存授予)的计划,具体取决于编译时优化器可见的查询中的任何值。不能使用查询存储或计划指南强制特定的内存授予。
3. 如何解决这个问题?
正如 Dan Guzman 的回答所暗示的那样,如果计划对特定参数值非常敏感,则使用OPTION (RECOMPILE)
提示在每次执行时编译新计划可能是最佳实用解决方案。
也就是说,可用于影响更新端执行计划的工具很少,这在涉及级联外键和索引视图之类的事情时可能很复杂。如果所有其他方法都失败了,您可能会发现没有排序的执行计划(按索引键顺序对行进行排序)会产生最好的结果。我知道没有记录在案的方法可以在没有这些类型的情况下生成计划,但是您可以尝试强制使用未记录的跟踪标志 8795获得的计划。
您还可以尝试使用合适的MAX_GRANT_PERCENT
查询提示或简单地安装(或提供给 SQL Server)足够的内存来处理您的工作负载。
两个计划都具有Optimized="false"
内部连接并且具有相同的形状。我从引用的博客文章中了解到,内存授予问题,其中外部表估计用于授予,仅适用于Optimized="true"
. 此外,对于嵌套循环外部表(带有已删除课程 ID 的表假脱机),这些计划的行数均为 1。
我怀疑经典参数嗅探。在 CoursePrerequisiteAssignment 聚集索引删除(级联删除?)之前,嵌套循环运算符的估计行数在顶部计划中约为 2500 万,而在底部计划中为 240。这可能是驱动所需内存的原因。
OPTION(RECOMPILE)
可能是最简单和最好的解决方案。另外,索引调整可能有助于避免CoursePrerequisiteAssignment
每次删除课程时对表进行全面扫描。
归档时间: |
|
查看次数: |
2771 次 |
最近记录: |