在“查询存储”下的数据库属性中,“统计信息收集间隔”设置为 1 小时。通过查询视图也证实了这一点query_store_runtime_stats_interval
- 所有间隔恰好为 1 小时。但是,当查看“总体资源消耗”等报告时,可以在“聚合大小”下拉列表中选择“分钟”,它会显示看起来合理的数据。
我能够捕获“顶级资源消耗查询报告”中使用的查询,它看起来显示了所有计划,这些计划也在选定的 1 分钟间隔内执行,但统计信息似乎仍然指的是完整的收集间隔。所以我的猜测是不要相信任何小于收集间隔的间隔。我的说法是否正确,或者报告是否确实显示了可靠的数据?
SELECT TOP (@results_row_count)
p.query_id query_id
, q.object_id object_id
, ISNULL(OBJECT_NAME(q.object_id),'') object_name
, qt.query_sql_text query_sql_text
, ROUND(CONVERT(float, SUM(rs.avg_duration*rs.count_executions))*0.001,2) total_duration
, SUM(rs.count_executions) count_executions
, COUNT(distinct p.plan_id) num_plans
FROM sys.query_store_runtime_stats rs
JOIN sys.query_store_plan p ON p.plan_id = rs.plan_id
JOIN sys.query_store_query q ON q.query_id = p.query_id
JOIN sys.query_store_query_text qt ON q.query_text_id = qt.query_text_id
WHERE NOT (rs.first_execution_time > @interval_end_time OR rs.last_execution_time < @interval_start_time)
GROUP BY p.query_id, qt.query_sql_text, q.object_id
HAVING COUNT(distinct p.plan_id) >= 1
ORDER BY total_duration DESC
您可以在查询中看到,他们正在做的事情是从第一次执行或最后一次执行的日期时间间隔内捕获内容,该日期时间落在报告的更窄的时间范围内。因此,它将包含一些非常准确的数据。但是,如果某个查询在该时间范围内执行,但它的第一次和最后一次执行时间超出了您感兴趣的时间间隔,您将看不到它。查询存储中存储的数据仅是聚合的,按收集间隔聚合。没有第二层、更深层次的数据或类似的东西。
感谢@Grant 确认收集间隔确实设置了数据的粒度。我对这些查询进行了更多研究,并想对有关准确性的部分进行一些扩展。
据我了解查询(*),执行和报告间隔只需要重叠,计划就会列在“顶级资源消耗查询报告”中。因此,数据的准确性很大程度上取决于计划执行的频率。在繁忙的应用程序数据库上,相同的查询将被一遍又一遍地使用,基本上将第一次和最后一次执行时间设置为等于收集间隔。假设执行次数均匀分布,则报告中显示的数据将相差 60 倍。
更让人吃惊的是《资源消耗总体报告》中的数据:
当我第一次看到这些图表时,我吓坏了。是什么可能导致我的数据库在每小时结束时出现这些峰值?幸运的是,事实是:峰值并不真实。
报告的查询已发布在这里,其中关键部分是:
存储桶由上次执行时间决定,这将等于我之前提到的许多查询的收集间隔的结束时间。
结论:这是一个小小的警示故事,说明试图报告不存在的信息将如何产生虚假结果。微软不会警告您,您将看到无意义的内容。我在互联网上也找不到有关此问题的任何信息。因此,对于任何深入研究报告并发现看起来有趣的数字的人来说,请放松。检查您的收集间隔,不要低于它。
(*) NOT(x OR y) 为真,当 x 和 y 均为假时,其中
x = rs.first_execution_time > @interval_end_time 和
y = rs.last_execution_time < @interval_start_time
这意味着计划必须在报告结束时间之前首先执行,反之亦然。