完全相同的查询和计划,但持续时间和总读取量不同。我知道参数嗅探但是

Gio*_*Gio 5 sql-server availability-groups sql-server-2014 enterprise-edition

我知道什么是参数嗅探,但这似乎不同,我有一个简单的查询:

select * from A400RDATA
Run Code Online (Sandbox Code Playgroud)

该表只有 acluster index和大约25000行。查询通常需要 1 秒,但现在需要 20 秒。

我在缓存中找到了它的执行计划,并使用sp_BlitzCache(感谢 Brent Ozar)分析每个细节 -> 是的,最后一次执行需要 20 秒。

因此,我稍作更改,再次运行此查询,前导空格:“ select * from A400RDATA”(注意sof之前的前导空格select)。前导空格是查询文本中的更改,因此会SQL Optimizer生成新的查询计划。

这两个查询计划是相同的,它们是平凡的计划,它们只是使用cluster index,但总读取和持续时间不同。遵循两种不同的 BlitzCache 结果:

在此处输入图片说明

Solarwind 显示下降Page Life Expectancy,并且 SQL Server 实例仅使用一个核心 ( MAXDOP = 1)。
我认为MAXDOP并且PLE可能是问题的原因,你怎么看?我怎么能确定呢?
我如何知道数据是从磁盘还是 RAM 中获取的?

我检查了20秒执行计划的逻辑和物理读取:

  • 执行时间:3
  • 物理读取:0
  • 处理的行数:76000
  • 逻辑写入:0
  • 逻辑读取:3841

没有物理读取......所以PLE不是原因(也许)。我再次阅读了计划的详细信息:3 次执行和 20 秒的总持续时间,因此每次执行需要 6 秒,但 CPU 时间相对较少:

  • 总持续时间(毫秒)= 20,013.84
  • 总 CPU (ms) = 192.57

会不会是CPU的问题?也许只有一个 CPU 是不够的,SQL 使查询处于 RUNNABLE 状态(等待 CPU 时间)。

Han*_*dyD 4

这两个查询计划是相同的,它们都是简单的计划,并且只使用簇索引,但总读取次数和持续时间不同。下面是两个不同的 BlitzCache 结果:

该结果集中的总读取量很可能是多次执行的总和。看到总行数列是 76,218,但最小值、最大值和平均值与其他执行相同?这表明原来的计划已经执行了 3 次,所以不要看总数,看平均值,这是相同的。

您需要查看这些读取是逻辑读取还是物理读取,因为执行时间的差异表明它们可能是逻辑读取,而物理读取差异可能会更清楚地说明您的情况。

Solarwind 显示页面预期寿命下降,并且 Sql 服务器实例仅使用一个核心 (MAXDOP = 1)。我认为 MAXDOP 和 PLE 可能是问题的原因,您有何看法?我如何确定这一点?我如何知道数据是从磁盘还是内存中获取的?

如果只有一个核心,则两个查询执行都将使用 MAXDOP = 1,因此不太可能导致任何变化。PLE 可能是导致性能问题的更深层次问题的症状,但这不是根本原因。如果您发现 PLE 持续较低或具有极端锯齿模式,您可能会发现确定其根本原因有助于识别此查询的问题。

您所描述的内容听起来不像参数嗅探,因为您的查询没有 WHERE 子句。听起来查询必须在第一次执行(物理读取)时从磁盘读取页面到缓冲区高速缓存中,并且后续读取发生在内存中(逻辑读取),这通常比物理读取快得多。

请查看这篇文章,了解物理读取与逻辑读取的描述。基本上,当您第一次执行时,需要 20 秒,这是由从磁盘读取页面引起的。由于微小的更改或新计划(正如您所说,实际计划是相同的),下一次执行速度并不快,而是因为这些数据页是从内存而不是磁盘读取的。如果您要刷新缓冲区缓存并再次重新运行查询,您可能会看到相同的行为 - 第一次执行 = 20 秒,第二次执行 = 1 秒。

您可以强制发生此行为以实时查看它。在非生产服务器上,运行以下命令:

DBCC DROPCLEANBUFFERS

SET STATISTICS IO ON

SELECT * FROM A400RDATA

SET STATISTICS IO OFF
Run Code Online (Sandbox Code Playgroud)

查看消息窗格中的输出并记下物理读取和逻辑读取值。再次运行以下行:

SET STATISTICS IO ON

SELECT * FROM A400RDATA

SET STATISTICS IO OFF
Run Code Online (Sandbox Code Playgroud)

检查输出并再次比较物理读取和逻辑读取值。物理读取应该显着下降,很可能下降到 0,而逻辑读取将相同或更高,表明现在从内存读取页面,而无需回退到磁盘读取。执行时间也应该更快。

对于已经执行的查询,我们如何在生产中确认这一点?如果没有事先进行监控和指标收集,就很难确定,但是,如果您使用计划句柄查询sys.dm_exec_query_stats,您可以获得最近执行的统计信息。检查最后、最小和最大物理读取次数。如果 min 为 0 并且 max 为更高的数字,则表示某些执行正在从磁盘读取。如果查询执行已返回到 1 秒,则最后一个应该是 0 或某个非常低的数字。

还要检查该 DMF 中的最后、最短和最大经过时间列,看看 20 秒执行计划的执行时间是否存在差异,我怀疑会有差异。Solarwinds 可以帮助您将 PLE 的下降与此查询的执行时间的增加关联起来,因为 PLE 的下降可能表明这些数据页已过期/被强制从缓存中移出,并导致物理读取增加。查看本文,了解有关优化/管理 PLE 以维护服务器性能的有用提示。

  • 值得一提的是,由于这些查询的 CPU 和持续时间之间存在巨大差异,因此 OP 还应该检查等待统计信息。它看起来很可能正在等待资源(比如您提到的 I/O,或者是“SOS_SCHEDULER_YIELD”的 CPU 或相关的 CPU 等待),或者它被其他查询阻塞,从而等待锁。 (2认同)