Joh*_* N. 7 sql-server execution-plan sql-server-2016
我目前正在调查一个应用程序,该应用程序似乎针对它正在查询的数据库生成 99% 的即席查询计划。我可以通过运行以下语句来检索查询计划缓存中的对象摘要来验证这一点:
抱歉无法在 SE 编辑器中输入代码,因此截图
参考:计划缓存和优化临时工作负载(SQLSkills.com / K. Tripp) 稍作修改
上述查询的结果如下:
CacheType Total Plans Total MBs Avg Use Count Total MBs - USE Count 1 Total Plans - USE Count 1
-------------------- -------------------- --------------------------------------- ------------- --------------------------------------- -------------------------
Adhoc 158997 5749.520042 2 2936.355979 126087
Prepared 1028 97.875000 695 46.187500 576
Proc 90 69.523437 39659 21.187500 21
View 522 75.921875 99 0.453125 3
Rule 4 0.093750 22 0.000000 0
Trigger 1 0.070312 12 0.000000 0
Run Code Online (Sandbox Code Playgroud)
在计划缓存中的 158'997 个即席查询中,126'087 个查询只执行了一次。
在进一步检查即席查询时,我发现有些查询甚至生成了多次。我使用以下查询检查了计划缓存以检索相同的执行计划:
SELECT SUM(cplan.usecounts) AS [Unique Same Single Plans],
qtext.text
FROM sys.dm_exec_cached_plans AS cplan
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS qtext
CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qplan
JOIN sys.databases AS sdb
ON sdb.database_id = qplan.dbid
WHERE 1 = 1
AND cplan.objtype = 'Adhoc' -- <-- only Adhoc plans
AND sdb.name = 'DATABASENAME' -- <-- for a certain database
AND cplan.usecounts = 1 -- <-- with a usecounts of 1
GROUP BY
qtext.text having sum(cplan.usecounts) > 1
ORDER BY
1 DESC --,cplan.objtype, cplan.usecounts
Run Code Online (Sandbox Code Playgroud)
参考资料:不记得了。让我知道它是否最初是你的,我会归于它。
这为我提供了一个即席查询列表,这些查询的查询计划与现有的相同查询计划相同,以及计划缓存中唯一相同查询计划的总和。
正如您从编辑后的 GUID 中看到的那样,有许多已多次创建的独特的即席查询计划。
为了证明我正朝着正确的方向前进,我从上面获取了一个唯一计数为 3 的语句,并将该语句用作我的计划缓存摘要语句中的过滤器来检索语句和查询计划:
SELECT cplan.usecounts,
qtext.text,
qplan.query_plan
FROM sys.dm_exec_cached_plans AS cplan
CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS qtext
CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qplan
JOIN sys.databases AS sdb
ON sdb.database_id = qplan.dbid
WHERE 1 = 1
AND cplan.objtype = 'Adhoc'
AND sdb.name = 'DATABASENAME'
AND qtext.text =
'SELECT description,id,name,osguid,profil FROM omitted WHERE osguid IN (SELECT osgroupguid FROM omitted WHERE osuserguid=''81C4B8_REMOVED_SOME_9DD2'')'
ORDER BY
1 DESC
Run Code Online (Sandbox Code Playgroud)
参考资料:不记得了。让我知道它是否最初是你的,我会归于它。
这为我提供了已创建并存储在计划缓存中的唯一临时查询列表:
现在上面屏幕截图中的数字表明,一个查询已经再次被重用,因为它的计数为 3。但是,所有查询都是相同的。
现在,根据我目前所读到的内容,我假设:
Adhoc
计划缓存中创建一个条目我同样意识到:
optimize for ad hoc workloads
对于仅使用一次的即席计划,打开将导致缓存中查询计划的大小略有减少ALTER DATABASE [DATABASENAME] SET PARAMETERIZATION FORCED
就我而言,跑步可能是个好主意,但是……
在阅读了所有文章以及在键入此问题时弹出的一些相关问题后,我有以下两个问题:
我意识到我的问题是矛盾的,因为非参数化查询计划被认为是唯一的,但为什么一些非参数化即席查询计划仍然被再次重用?
以 XML 格式保存“相同”查询的计划并比较文件,我认为可能存在一些差异(例如,在设置选项中)– Denis Rubashkin 29 分钟前
SET 选项是相同的。整个计划的唯一区别是<StatementSetOptions>
在CompileTime
和部分之后的第二行CompileCPU
。我在下面粘贴了两个相关部分:
<StatementSetOptions QUOTED_IDENTIFIER="true" ARITHABORT="false" CONCAT_NULL_YIELDS_NULL="true" ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" NUMERIC_ROUNDABORT="false" />
<QueryPlan CachedPlanSize="32" CompileTime="4" CompileCPU="4" CompileMemory="472">
Run Code Online (Sandbox Code Playgroud)
<StatementSetOptions QUOTED_IDENTIFIER="true" ARITHABORT="false" CONCAT_NULL_YIELDS_NULL="true" ANSI_NULLS="true" ANSI_PADDING="true" ANSI_WARNINGS="true" NUMERIC_ROUNDABORT="false" />
<QueryPlan CachedPlanSize="32" CompileTime="3" CompileCPU="3" CompileMemory="472">
Run Code Online (Sandbox Code Playgroud)
没有发现其他差异。
用于策划此问题的参考资料:
打开临时工作负载的优化将导致缓存中查询计划的大小略有减少
...
在计划缓存中的 158'997 个即席查询中,126'087 个仅执行了一次。
我不认为删除 79% 的 AdHoc 计划只是轻微减少。
在哪些情况下会重用非参数化、重要的即席查询计划?
当连接到同一数据库的客户端在缓存中运行计划后,运行具有相同会话设置的完全相同的查询时。
所以,
为什么相同的语句有多个缓存的查询计划?
通常,具有不同设置的会话会影响查询行为。查询中的任何文本差异(包括空格)都可能导致此问题。用户的默认架构可能会导致这种情况,因为对象名称解析不同。此外,几乎同时提交的两个相同的查询可能会得到独立的优化和缓存。
归档时间: |
|
查看次数: |
165 次 |
最近记录: |