AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / dba / 问题 / 252575
Accepted
John K. N.
John K. N.
Asked: 2019-11-06 04:05:22 +0800 CST2019-11-06 04:05:22 +0800 CST 2019-11-06 04:05:22 +0800 CST

何时重用非参数化、非平凡、即席查询计划

  • 772

我目前正在研究一个应用程序,该应用程序似乎针对它正在查询的数据库生成 99% 的即席查询计划。我可以通过运行以下语句来检索查询计划缓存中的对象摘要来验证这一点:

抱歉无法在 SE 编辑器中输入代码,因此截图

select 语句查询 sys.dm_exec_cached_plans

参考:为临时工作负载规划缓存和优化(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    

在计划缓存中的 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   

参考:不记得了。让我知道它是否最初是你的,我会归于它。

这给了我一个即席查询列表,这些查询的查询计划与现有的相同查询计划相同,并且计划缓存中唯一相同的查询计划的总和。

包含唯一相同单一计划的结果集的屏幕截图

正如您从编辑的 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

参考:不记得了。让我知道它是否最初是你的,我会归于它。

这给了我一个独特的即席查询列表,这些查询已经创建并存储在计划缓存中:

包含唯一相同单一计划的结果集的屏幕截图

现在上面屏幕截图中的数字表明一个查询已经被再次重用,因为它的计数为 3。但是,所有查询都是相同的。

现在从我到目前为止所读到的,我假设:

  • 即席查询是在其(可能很短的)生命周期中第一次传递给 SQL Server 查询优化器的查询
  • 没有参数的语句被认为是唯一的,并将导致在Adhoc计划缓存中创建一个条目
  • 即席查询可能很简单,这会导致为每个语句创建单独的查询计划,即使它们是相同的

我同样意识到:

  • 打开optimize for ad hoc workloads将导致缓存中查询计划的大小略有减少,用于仅使用一次的临时计划
  • 就我而言,跑步ALTER DATABASE [DATABASENAME] SET PARAMETERIZATION FORCED可能是一个好主意,但是...
    • 有限制(见 BrentOzar 的文章)
    • 程序中的参数化会更好

问题

在阅读了所有文章和输入此问题时弹出的一些相关问题后,我有以下两个问题:

  1. 在哪些情况下会重用非参数化、非平凡、即席查询计划?
  2. 为什么相同语句有多个缓存查询计划?

我意识到我的问题是矛盾的,因为非参数化查询计划被认为是唯一的,但为什么一些非参数化即席查询计划仍然被再次重用?


回应@DenisRubashikin 的评论:

以 XML 格式保存“相同”查询的计划并比较文件,我认为可能存在一些差异(例如,在设置选项中)– Denis Rubashkin 29 分钟前

SET 选项是相同的。整个计划的唯一区别是在和<StatementSetOptions>部分之后的第二行。我在下面粘贴了两个相关部分:CompileTimeCompileCPU

查询计划1.xml

      <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">

查询计划2.xml

      <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">

未发现其他差异。


用于解决此问题的参考资料:

  • 针对临时工作负载规划缓存和优化(SQLSkills.com)
  • 查询处理架构指南(Microsoft SQL Docs)
  • ALTER DATABASE SET 选项 (Transact-SQL) (Microsoft SQL Docs)
  • 为什么一个查询的多个计划不好(BrentOzar.com)
  • 强制参数化会出错吗?(BrentOzar.com)
  • 闪电战结果:强制参数化(Brentoar.com)
sql-server sql-server-2016
  • 1 1 个回答
  • 218 Views

1 个回答

  • Voted
  1. Best Answer
    David Browne - Microsoft
    2019-11-06T12:57:02+08:002019-11-06T12:57:02+08:00

    为临时工作负载启用优化将导致缓存中查询计划的大小略有减少

    ...

    在计划缓存中的 158'997 个即席查询中,126'087 个只执行了一次。

    我不会将删除 79% 的 AdHoc 计划称为略微减少。

    在哪些情况下会重用非参数化、非平凡、即席查询计划?

    当计划在缓存中由连接到同一数据库的客户端运行后,运行完全相同的查询,具有相同的会话设置。

    所以,

    为什么相同语句有多个缓存查询计划?

    通常,具有不同设置的会话会影响查询行为。查询中的任何文本差异(包括空格)都可能导致此问题。用户的默认模式可能会导致这种情况,因为对象名称解析不同。此外,几乎同时提交的两个相同查询可能会被独立优化和缓存。

    • 3

相关问题

  • SQL Server - 使用聚集索引时如何存储数据页

  • 我需要为每种类型的查询使用单独的索引,还是一个多列索引可以工作?

  • 什么时候应该使用唯一约束而不是唯一索引?

  • 死锁的主要原因是什么,可以预防吗?

  • 如何确定是否需要或需要索引

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目

    • 12 个回答
  • Marko Smith

    如何让sqlplus的输出出现在一行中?

    • 3 个回答
  • Marko Smith

    选择具有最大日期或最晚日期的日期

    • 3 个回答
  • Marko Smith

    如何列出 PostgreSQL 中的所有模式?

    • 4 个回答
  • Marko Smith

    列出指定表的所有列

    • 5 个回答
  • Marko Smith

    如何在不修改我自己的 tnsnames.ora 的情况下使用 sqlplus 连接到位于另一台主机上的 Oracle 数据库

    • 4 个回答
  • Marko Smith

    你如何mysqldump特定的表?

    • 4 个回答
  • Marko Smith

    使用 psql 列出数据库权限

    • 10 个回答
  • Marko Smith

    如何从 PostgreSQL 中的选择查询中将值插入表中?

    • 4 个回答
  • Marko Smith

    如何使用 psql 列出所有数据库和表?

    • 7 个回答
  • Martin Hope
    Jin 连接到 PostgreSQL 服务器:致命:主机没有 pg_hba.conf 条目 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane 如何列出 PostgreSQL 中的所有模式? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh 为什么事务日志不断增长或空间不足? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland 列出指定表的所有列 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney MySQL 能否合理地对数十亿行执行查询? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx 如何监控大型 .sql 文件的导入进度? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison 你如何mysqldump特定的表? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 对 SQL 查询进行计时? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas 如何从 PostgreSQL 中的选择查询中将值插入表中? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas 如何使用 psql 列出所有数据库和表? 2011-02-18 00:45:49 +0800 CST

热门标签

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve