查询存储中的“执行计数”是什么?

ada*_*m.g 3 sql-server sql-server-2016 query-store

我们正在使用 SQL Server 2016。我们在 2023 年 9 月 11 日的查询持续时间方面遇到一些问题。想在 QueryStore 上检查它,我在 2023 年 9 月 11 日 05:00 PM 执行的查询存储上看到:

在此输入图像描述

2023 年 9 月 11 日,我们的执行次数要多得多(2023 年 9 月 8 日,执行次数约为 1150 VS 800)。我在 2023 年 9 月 12 日运行相同的查询存储检查,发现昨天的执行计数比我昨天检查的要少得多。

你知道为什么我们会有这样的差异吗?更重要的是,我仍然看到 2023 年 9 月 11 日的执行计数仍在减少。

在此输入图像描述

添加了查询存储设置。在此输入图像描述

查询执行 2023-09-14 9:52 AM:

在此输入图像描述

查询执行 2023-09-14 10:53 AM: 在此输入图像描述

查询执行 2023-09-14 12:36 PM:甚至 2023-09-11 也已更改...在此输入图像描述

Zik*_*ato 12

GUI 中的查询存储执行计数映射到sys.query_store_runtime_stats中的count_executions

聚合间隔内查询计划的执行总数。

由于您正在查看“总体资源消耗”,因此我捕获了使用扩展事件调用的基础查询,大致如下:

SELECT
    CONVERT(float, SUM(rs.count_executions)) as total_count_executions,
    ROUND(CONVERT(float, SUM(rs.avg_duration*rs.count_executions))*0.001,2) as total_duration,
    ROUND(CONVERT(float, SUM(rs.avg_cpu_time*rs.count_executions))*0.001,2) as total_cpu_time,
    ROUND(CONVERT(float, SUM(rs.avg_logical_io_reads*rs.count_executions))*8,2) as total_logical_io_reads,
    ROUND(CONVERT(float, SUM(rs.avg_logical_io_writes*rs.count_executions))*8,2) as total_logical_io_writes,
    ROUND(CONVERT(float, SUM(rs.avg_physical_io_reads*rs.count_executions))*8,2) as total_physical_io_reads,
    ROUND(CONVERT(float, SUM(rs.avg_clr_time*rs.count_executions))*0.001,2) as total_clr_time,
    ROUND(CONVERT(float, SUM(rs.avg_dop*rs.count_executions))*1,0) as total_dop,
    ROUND(CONVERT(float, SUM(rs.avg_query_max_used_memory*rs.count_executions))*8,2) as total_query_max_used_memory,
    ROUND(CONVERT(float, SUM(rs.avg_rowcount*rs.count_executions))*1,0) as total_rowcount,
    ROUND(CONVERT(float, SUM(rs.avg_log_bytes_used*rs.count_executions))*0.0009765625,2) as total_log_bytes_used,
    ROUND(CONVERT(float, SUM(rs.avg_tempdb_space_used*rs.count_executions))*8,2) as total_tempdb_space_used,
    DATEADD(d, ((DATEDIFF(d, 0, rs.last_execution_time))),0 ) as bucket_start,
    DATEADD(d, (1 + (DATEDIFF(d, 0, rs.last_execution_time))), 0) as bucket_end
FROM sys.query_store_runtime_stats rs
WHERE NOT (rs.first_execution_time > @interval_end_time OR rs.last_execution_time < @interval_start_time)
GROUP BY DATEDIFF(d, 0, rs.last_execution_time)
Run Code Online (Sandbox Code Playgroud)

由于除了日期之外几乎没有过滤器,因此只剩下几个选项。

  1. 你的声明没有被调用。也许那天没有进行测试,也许你的代码有一些分支逻辑等等。

  2. 有人使用sp_query_store_remove_query或使用sp_query_store_remove_plan的查询计划仅从查询存储中清除了该查询

  3. 查询存储暂时切换为只读。您无法在事后检查这一点,但如果您怀疑是这种情况,可以选择在将来使用扩展事件来监视这一点

编辑

在提供了更多信息之后,我倾向于指出SIZE_BASED_CLEANUP_MODE

文档

1 = AUTO - 当磁盘大小达到 max_storage_size_mb 的 90% 时,将自动激活基于大小的清理。这是默认配置值。

基于大小的清理首先删除最便宜和最旧的查询。当达到 max_storage_size_mb 的大约 80% 时,它会停止。

这与您的屏幕截图相符,即已使用 100 MB 中的 79 MB(大约 80%)

您可以创建一个 XE 会话来跟踪此清理并确保

CREATE EVENT SESSION [QueryStoreCleanup] ON SERVER 
ADD EVENT qds.query_store_size_retention_cleanup_finished,
ADD EVENT qds.query_store_size_retention_cleanup_started,
ADD EVENT qds.query_store_size_retention_cleanup_update
ADD TARGET package0.event_file
(
    SET filename=N'QueryStoreCleanup'
    , max_file_size = 5
    , max_rollover_files = 1 
)
GO

ALTER EVENT SESSION [QueryStoreCleanup] ON SERVER STATE = START
Run Code Online (Sandbox Code Playgroud)

我已经在最大大小 = 10 MB 的查询存储上对其进行了测试,它大约每 15 - 20 分钟运行一次。

在此输入图像描述

我运行了一堆动态 SQL 来让查询存储增长,并捕获清理前后的执行和计划计数聚合。

在此输入图像描述

我所有的动态 SQL 都同样昂贵,因此最旧的计划首先被淘汰。