Encontrar consultas con mayor consumo total de CPU

El uso de CPU es elevado o presenta picos repetidos. Antes de revisar planes al azar, necesitamos localizar las sentencias terminadas que más CPU han acumulado entre los planes todavía presentes en caché.

Qué necesitamos distinguir

CPU es el tiempo de procesador consumido por el trabajo. La caché de planes conserva estrategias compiladas para reutilizarlas; si un plan sale de ella, sus métricas acumuladas dejan de aparecer en esta consulta.

El consumo total favorece consultas ejecutadas muchas veces; el promedio ayuda a detectar ejecuciones individualmente costosas. Ambas medidas pertenecen al ciclo de vida del plan almacenado y no constituyen un historial permanente del servidor.

Consulta

/*
    Antes de ejecutar:
        Revisa los permisos y los límites antes de ejecutar la consulta.
        Confirma el alcance, la base activa y el costo posible de la consulta.
        Captura evidencia en varios momentos antes de atribuir una causa.

    Este script es de observación. No aplica correcciones ni modifica datos.
*/

SET NOCOUNT ON;
GO
-- Consulta
DECLARE @Cantidad INT = 25;

SELECT TOP (@Cantidad)
    DB_NAME(st.dbid) AS BaseDatos,
    OBJECT_SCHEMA_NAME(st.objectid, st.dbid) AS Esquema,
    OBJECT_NAME(st.objectid, st.dbid) AS Objeto,
    qs.execution_count AS Ejecuciones,
    CONVERT(DECIMAL(18, 2), qs.total_worker_time / 1000.0) AS CpuTotalMs,
    CONVERT
    (
        DECIMAL(18, 2),
        qs.total_worker_time / NULLIF(qs.execution_count, 0) / 1000.0
    ) AS CpuPromedioMs,
    qs.creation_time AS PlanCreado,
    qs.last_execution_time AS UltimaEjecucion,
    SUBSTRING
    (
        st.text,
        (qs.statement_start_offset / 2) + 1,
        ((CASE qs.statement_end_offset
            WHEN -1 THEN DATALENGTH(st.text)
            ELSE qs.statement_end_offset
          END - qs.statement_start_offset) / 2) + 1
    ) AS Sentencia
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) AS st
WHERE qs.execution_count > 0
ORDER BY
    qs.total_worker_time DESC,
    qs.execution_count DESC;
GO

Parámetros o permisos

@Cantidad limita la revisión inicial. La consulta requiere VIEW SERVER STATE, o VIEW SERVER PERFORMANCE STATE desde SQL Server 2022. El tiempo de CPU se reporta en microsegundos, con precisión de milisegundos, y aquí se convierte a milisegundos. Una misma construcción lógica puede aparecer en varias filas por recompilaciones, parámetros, bases de contexto o planes distintos. Los objetos ad hoc pueden no tener nombre de esquema u objeto.

Cómo leer el resultado

Empieza por CpuTotalMs para reconocer impacto acumulado. Después contrástalo con Ejecuciones y CpuPromedioMs: una sentencia barata pero muy frecuente puede superar a otra cara que se ejecuta pocas veces. PlanCreado delimita desde cuándo se han acumulado los contadores de esa fila. Sentencia extrae el fragmento correspondiente dentro del lote, no necesariamente el lote completo.

Qué conclusión sí permite obtener

Permite priorizar sentencias terminadas cuyos planes siguen en caché y que han concentrado más CPU total durante la vida de esos planes.

Qué conclusión todavía no permite obtener

No muestra consultas en curso, entradas expulsadas de caché ni consumo anterior a una recompilación. Un total alto tampoco prueba que la sentencia esté mal diseñada: puede corresponder a una carga necesaria y frecuente.

Siguiente comprobación razonable

Revisa también las consultas con mayor lectura lógica y mayor duración. Para una candidata concreta, recupera el plan almacenado y confirma el comportamiento con una ejecución controlada.

Índice del recorrido

Diagnóstico y optimización

23 artículos de Diagnóstico y optimización
  1. 01Ver solicitudes activas y su consulta SQL
  2. 02Identificar sesiones bloqueadoras y bloqueadas
  3. 03Construir la cadena de bloqueo
  4. 04Encontrar transacciones abiertas por mucho tiempo
  5. 05Encontrar sesiones inactivas con transacción abierta
  6. 06Ver esperas de las solicitudes activas
  7. 07Revisar las principales esperas acumuladas
  8. 08Encontrar consultas con mayor consumo total de CPU
  9. 09Encontrar consultas con mayor lectura lógica
  10. 10Encontrar consultas con mayor duración promedio
  11. 11Recuperar el plan de ejecución almacenado
  12. 12Revisar sugerencias de índices faltantes
  13. 13Revisar uso de índices
  14. 14Revisar fragmentación de índices con alcance controlado
  15. 15Revisar antigüedad y modificación de estadísticas
  16. 16Medir el uso de espacio y log de cada base
  17. 17Diagnosticar por qué el log no puede reutilizarse
  18. 18Recuperar deadlocks recientes de system_health
  19. 19Encontrar consultas degradadas mediante Query Store
  20. 20Encontrar sesiones y solicitudes que consumen tempdb
  21. 21Revisar concesiones de memoria pendientes o excesivas
  22. 22Calcular latencia de lectura y escritura por archivo
  23. 23Encontrar consultas con varios planes y rendimientos diferentes