Durante la investigación de una consulta lenta, parecía que el plan de ejecución era excepcionalmente subóptimo (un bucle anidado que realizaba 9 millones de ejecuciones de una búsqueda donde el número estimado de ejecuciones era 1). Habiendo confirmado que algunas estadísticas relevantes donde realmente estaban desactualizadas, reconstruí las estadísticas y el problema de rendimiento se resolvió efectivamente.
Esta base de datos tiene habilitadas las estadísticas de actualización automática (activada de manera predeterminada). Entiendo que hay un umbral para las actualizaciones de estadísticas automáticas en función de que haya un 20% + 500 modificaciones de fila (actualización / inserción / eliminación). Este umbral parece haber sido excedido en gran medida en múltiples índices, por lo que parece que hay (A) un problema con las actualizaciones automáticas o (B) Hay más en la estrategia de actualización de lo que he podido encontrar en línea documentación.
Aprecio que se pueda configurar una tarea programada para actualizar las estadísticas y es probable que este sea el enfoque que adoptemos si no se puede encontrar otra solución, pero nos deja confundidos sobre por qué un número tan grande de modificaciones no desencadenaría actualización automática para algunas estadísticas: comprender por qué podría ayudarnos a decidir qué estadísticas deben actualizarse mediante una tarea programada.
Algunas notas adicionales:
1) El problema se observó en una base de datos donde los datos se crean mediante una prueba de carga y, como tal, se agrega una gran cantidad de datos en un corto espacio de tiempo, por lo tanto, si la actualización automática se produce periódicamente (por ejemplo, una vez al día al la mayoría) entonces esto puede explicar algunos de los comportamientos observados. Además, nuestras pruebas de carga tienden a estresar mucho la base de datos, por lo tanto, me pregunto si SQL está aplazando las actualizaciones de estadísticas mientras haya una carga pesada (y posteriormente no actualiza las estadísticas por alguna razón).
2) Al tratar de recrear este problema con un script de prueba que contiene sucesivas instrucciones INSERT, SELECT y DELETE, el problema no se produjo. Me pregunto si la distinción aquí es que estas declaraciones afectan a muchas filas por declaración SQL, mientras que nuestro script de prueba de carga tenderá a insertar filas individualmente.
3) La base de datos en cuestión se establece en el modelo de recuperación 'Simple'.
Algunos enlaces relevantes:
- Lista de verificación para analizar consultas de ejecución lenta
- Uso de estadísticas para mejorar el rendimiento de las consultas
También he planteado este problema a través de Microsoft Connect:
ACTUALIZACIÓN 2011-06-30:
En una investigación adicional, creo que las estadísticas que están desactualizadas más allá de los niveles de umbral (por ejemplo, 500 filas + 20%) son estadísticas que no están siendo utilizadas por la consulta del problema, por lo tanto, probablemente se actualizarán cuando se ejecute una consulta eso los requiere. Para las estadísticas que son utilizados por la consulta, éstas se actualizan con regularidad. El problema restante es que estas estadísticas son muy engañosas para el optimizador del plan de consultas después de solo unas pocas inserciones (por ejemplo, causando los 9 millones más o menos mencionados donde el número estimado era 1).
Mi presentimiento en este momento es que el problema está relacionado con una mala elección de la clave primaria, la clave es un identificador único creado con NEWID (), y esto crea un índice altamente fragmentado muy rápidamente, especialmente como el factor de relleno predeterminado en SQL El servidor es 100%. Mi presentimiento es que esto de alguna manera da como resultado estadísticas engañosas después de relativamente pocas inserciones de fila, menos del umbral para volver a calcular las estadísticas. Posiblemente todo esto no sea un problema, ya que he generado una gran cantidad de datos sin reconstruir los índices a mitad de camino, por lo tanto, las estadísticas pobres pueden ser una consecuencia de la fragmentación del índice muy alta resultante. Creo que necesito agregar ciclos de mantenimiento de SQL Server en mi prueba de carga para tener una mejor idea del rendimiento en un sistema real durante largos períodos de tiempo.
ACTUALIZACIÓN 2012-01-10:
Otro factor a tener en cuenta. Se agregaron dos marcas de seguimiento a SQL Server 2005 (y parece que todavía están presentes en 2008) para abordar las deficiencias específicas relacionadas con la aparición de estadísticas obsoletas y / o engañosas. Las banderas en cuestión son:
DBCC TRACEON(2389)
DBCC TRACEON(2390)
MSDN: Weblog de Ian Jose: claves ascendentes y estadísticas de estadísticas corregidas automáticamente en columnas ascendentes, Fabiano Amorim
Por supuesto, debe tener mucho cuidado al decidir habilitar estas banderas, ya que pueden tener efectos perjudiciales.