Encontrar regresiones de plan con Query Store (misma consulta, planes distintos)
SQL ServerQuery StoreComando
USE [Musteri];
-- Queries with more than one plan in the last 24 hours, per-plan performance:
WITH plan_stats AS (
SELECT p.query_id, p.plan_id, p.is_forced_plan,
SUM(rs.count_executions) AS execs,
SUM(rs.avg_duration * rs.count_executions) / SUM(rs.count_executions) / 1000.0 AS avg_ms,
SUM(rs.avg_cpu_time * rs.count_executions) / SUM(rs.count_executions) / 1000.0 AS avg_cpu_ms,
SUM(rs.avg_logical_io_reads * rs.count_executions) / SUM(rs.count_executions) AS avg_reads,
MAX(rs.last_execution_time) AS last_exec
FROM sys.query_store_plan p
JOIN sys.query_store_runtime_stats rs ON rs.plan_id = p.plan_id
JOIN sys.query_store_runtime_stats_interval i
ON i.runtime_stats_interval_id = rs.runtime_stats_interval_id
WHERE i.start_time >= DATEADD(HOUR, -24, SYSUTCDATETIME())
GROUP BY p.query_id, p.plan_id, p.is_forced_plan
)
SELECT ps.query_id, ps.plan_id, ps.is_forced_plan, ps.execs,
CAST(ps.avg_ms AS DECIMAL(18,2)) AS avg_ms,
CAST(ps.avg_cpu_ms AS DECIMAL(18,2)) AS avg_cpu_ms,
CAST(ps.avg_reads AS BIGINT) AS avg_reads,
CAST(ps.avg_ms / NULLIF(MIN(ps.avg_ms) OVER (PARTITION BY ps.query_id), 0) AS DECIMAL(18,1)) AS x_slower_than_best,
ps.last_exec,
OBJECT_NAME(q.object_id) AS module,
LEFT(qt.query_sql_text, 120) AS query_text
FROM plan_stats ps
JOIN sys.query_store_query q ON q.query_id = ps.query_id
JOIN sys.query_store_query_text qt ON qt.query_text_id = q.query_text_id
WHERE ps.query_id IN (SELECT query_id FROM plan_stats GROUP BY query_id HAVING COUNT(*) > 1)
ORDER BY ps.query_id, ps.avg_ms;Qué hace
Encuentra consultas que se ejecutaron con más de un plan en las últimas 24 horas; muestra lado a lado el número de ejecuciones de cada plan, la duración/CPU/lecturas medias ponderadas y cuántas veces es más lento que el mejor plan.
Cuándo usarlo
Cuando una consulta "ayer iba rápida y hoy va lenta", tras una actualización de estadísticas, un cambio de índices, una actualización del nivel de compatibilidad o un parche.
Precaución
La duración media también depende de la distribución de los datos; al comparar planes que se ejecutaron con valores de parámetros distintos, mire también avg_reads (parameter sniffing). Las ventanas de tiempo están en UTC. Los resultados son estadísticamente débiles para planes con pocas ejecuciones. Consulta de solo lectura; segura.