我正在尝试分析 SQL Server 中特定对象的不同查询执行计划的性能。我的目标是检索前 5 个最有效的查询计划,以便我可以手动比较它们并选择最好的一个来强制执行。
背景 数据库:SQL Server 对象:[指定存储过程] 当前的方法:我一直在使用查询存储功能,但我不确定如何有效地过滤和排名计划。
我尝试过的: 我尝试使用以下 SQL 查询来检索执行计划,但没有得到所需的结果:
SELECT OBJECT_NAME(object_id), qp.plan_id, qt.query_sql_text, q.query_id, q.query_text_id,
qp.query_plan, q.avg_compile_memory_kb / 1024 AS avg_compile_memory_mb, q.last_execution_time
FROM sys.query_store_query_text qt
INNER JOIN sys.query_store_query q ON qt.query_text_id = q.query_text_id
INNER JOIN sys.query_store_plan qp ON qp.query_id = q.query_id
WHERE ISNULL(OBJECT_NAME(q.object_id), 'N/A') = 'axsp_upd_credit_utilisation2' -- Filter for specific object
AND qt.query_sql_text LIKE '%(@includeResidualValue bit%'
ORDER BY q.last_execution_time DESC;
问题
附加信息 我正在寻找 SQL Server 中有关执行计划分析的最佳实践。 任何有关为此目的有效使用查询存储的见解将不胜感激。
请查看我根据@Charlieface的建议创建的修改后的SQL。您能否确认它是否正确并达到其目的?
SELECT
o.name AS ObjectName,
qp.plan_id,
qt.query_sql_text,
q.query_id,
q.query_text_id,
qp.query_plan,
SUM(q.avg_compile_memory_kb) / 1024 AS total_compile_memory_mb, -- Aggregate memory usage
MAX(q.last_execution_time) AS last_execution_time,
qsr.execution_type,
AVG(qsr.avg_duration) AS avg_duration,
AVG(qsr.avg_cpu_time) AS avg_cpu_time,
AVG(qsr.avg_logical_io_reads) AS avg_logical_io_reads,
AVG(qsr.avg_physical_io_reads) AS avg_physical_io_reads,
SUM(qsr.count_executions) AS total_executions
FROM sys.query_store_query_text qt
JOIN sys.query_store_query q ON qt.query_text_id = q.query_text_id
JOIN sys.query_store_plan qp ON qp.query_id = q.query_id
JOIN sys.query_store_runtime_stats qsr ON qsr.plan_id = qp.plan_id
JOIN sys.objects o ON o.object_id = q.object_id
WHERE o.name = 'axsp_upd_credit_utilisation2' -- Filter for specific object
AND qt.query_sql_text LIKE '%(@includeResidualValue bit%' -- Filter for specific SQL text
GROUP BY
o.name,
qp.plan_id,
qt.query_sql_text,
q.query_id,
q.query_text_id,
qp.query_plan,
qsr.execution_type
ORDER BY
q.query_id,
qsr.execution_type, -- Regular execution first
avg_duration; -- Order by average duration
sys.query_store_runtime_stats
视图 获取每个计划的运行时统计信息。例如,您可以通过 avg_duration
列进行订购。
SELECT
o.name,
qp.plan_id,
qt.query_sql_text,
q.query_id,
q.query_text_id,
qp.query_plan,
q.avg_compile_memory_kb / 1024 AS avg_compile_memory_mb,
q.last_execution_time,
qsr.*
FROM sys.query_store_query_text qt
JOIN sys.query_store_query q ON qt.query_text_id = q.query_text_id
JOIN sys.query_store_plan qp ON qp.query_id = q.query_id
JOIN sys.query_store_runtime_stats qsr ON qsr.plan_id = qp.plan_id
JOIN sys.objects o ON o.object_id = q.object_id
WHERE o.name = 'axsp_upd_credit_utilisation2' -- Filter for specific object
AND qt.query_sql_text LIKE '%(@includeResidualValue bit%'
ORDER BY
q.query_id,
sqr.execution_type, -- regular exec first
sqr.avg_duration;
请注意此表:
仅对过去的运行时间统计间隔是唯一的。对于当前活动间隔,可能有多行表示
引用的计划的运行时统计信息,执行类型由plan_id
表示。通常,一行表示刷新到磁盘的运行时统计信息,而其他行表示内存中状态。因此,要获取每个时间间隔的实际状态,您需要聚合指标,按execution_type
、plan_id
和execution_type
进行分组。runtime_stats_interval_id
关于新修改的查询:与其进行巨大的低效
GROUP BY
,不如将计算放入APPLY
或JOIN
中。
SUM(q.avg_compile_memory_kb) / 1024 AS total_compile_memory_mb
是无意义的,它将总结可能多次代表相同计划的行。您可能想要 AVG
。
查看未完成运行的平均统计数据可能没有意义,仅查看常规运行。
SELECT
o.name AS ObjectName,
qp.plan_id,
qt.query_sql_text,
q.query_id,
q.query_text_id,
qp.query_plan,
q.avg_compile_memory_kb / 1024 AS total_compile_memory_mb, -- Aggregate memory usage
q.last_execution_time AS last_execution_time,
qsr.*
FROM sys.query_store_query_text qt
JOIN sys.query_store_query q ON qt.query_text_id = q.query_text_id
JOIN sys.query_store_plan qp ON qp.query_id = q.query_id
JOIN sys.objects o ON o.object_id = q.object_id
CROSS APPLY (
SELECT
AVG(qsr.avg_duration) AS avg_duration,
AVG(qsr.avg_cpu_time) AS avg_cpu_time,
AVG(qsr.avg_logical_io_reads) AS avg_logical_io_reads,
AVG(qsr.avg_physical_io_reads) AS avg_physical_io_reads,
SUM(qsr.count_executions) AS total_executions
FROM sys.query_store_runtime_stats qsr
WHERE qsr.plan_id = qp.plan_id
AND qsr.execution_type = 0 -- Regular execution only
GROUP BY
qsr.execution_type
) qsr
WHERE o.name = 'axsp_upd_credit_utilisation2' -- Filter for specific object
AND qt.query_sql_text LIKE '%(@includeResidualValue bit%' -- Filter for specific SQL text
ORDER BY
q.query_id,
avg_duration; -- Order by average duration