Revisar antigüedad y modificación de estadísticas

Un plan estima cantidades de filas muy distintas de las observadas o cambia de forma inesperada. Necesitamos saber cuándo se actualizaron sus estadísticas, cuánto se muestreó y cuántas modificaciones registra la columna principal del histograma.

Qué necesitamos distinguir

Una estadística resume la distribución de valores para ayudar al optimizador a estimar filas. El histograma divide valores en intervalos y la muestra es el subconjunto de filas utilizado para construir ese resumen.

La fecha por sí sola no determina si una estadística es adecuada. Una tabla estable puede conservar estadísticas antiguas y útiles; una distribución cambiante puede degradar estimaciones aunque la fecha parezca reciente.

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
SELECT
    sch.name AS Esquema,
    t.name AS Tabla,
    st.name AS Estadistica,
    st.auto_created AS CreadaAutomaticamente,
    st.user_created AS CreadaPorUsuario,
    st.no_recompute AS SinRecalculoAutomatico,
    st.has_filter AS TieneFiltro,
    st.filter_definition AS DefinicionFiltro,
    sp.last_updated AS UltimaActualizacion,
    sp.rows AS FilasAlActualizar,
    sp.rows_sampled AS FilasMuestreadas,
    CONVERT
    (
        DECIMAL(6, 2),
        100.0 * sp.rows_sampled / NULLIF(sp.rows, 0)
    ) AS MuestreoPorcentaje,
    sp.steps AS PasosHistograma,
    sp.modification_counter AS ModificacionesColumnaPrincipal,
    CONVERT
    (
        DECIMAL(8, 2),
        100.0 * sp.modification_counter / NULLIF(sp.rows, 0)
    ) AS ModificacionesPorcentaje
FROM sys.stats AS st
INNER JOIN sys.tables AS t
    ON t.object_id = st.object_id
INNER JOIN sys.schemas AS sch
    ON sch.schema_id = t.schema_id
OUTER APPLY sys.dm_db_stats_properties
(
    st.object_id,
    st.stats_id
) AS sp
WHERE t.is_ms_shipped = 0
ORDER BY
    sp.last_updated,
    sp.modification_counter DESC,
    sch.name,
    t.name,
    st.name;
GO

Parámetros o permisos

Ejecuta la consulta en la base investigada. Se necesitan permisos para consultar las columnas estadísticas, ser propietario de la tabla o pertenecer a una función con permisos suficientes. UltimaActualizacion puede ser NULL en una tabla nueva y vacía o en estadísticas filtradas cuyo predicado no produjo filas. ModificacionesColumnaPrincipal cuenta cambios relacionados con la primera columna de la estadística, no todas las modificaciones de la tabla.

Cómo leer el resultado

Compara FilasAlActualizar, FilasMuestreadas y el volumen actual de la tabla. Un porcentaje pequeño no es automáticamente incorrecto: el muestreo puede ser suficiente para una distribución, pero insuficiente para otra. SinRecalculoAutomatico merece atención porque evita actualizaciones automáticas de esa estadística. Los porcentajes calculados sirven para priorizar la revisión, no como un umbral fijo de mantenimiento.

Qué conclusión sí permite obtener

Permite encontrar estadísticas antiguas, poco muestreadas o con cambios acumulados y reunir el contexto necesario para revisar una estimación problemática.

Qué conclusión todavía no permite obtener

No demuestra que una estadística esté causando un plan deficiente ni determina el método de actualización apropiado. Tampoco muestra por sí sola la distribución del histograma.

Siguiente comprobación razonable

Compara las filas estimadas y observadas del plan de ejecución recuperado. Para una estadística candidata, revisa sus columnas, filtro e histograma antes de decidir una actualizació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