Rendimiento del servidor SQL degradación repentina

13

Tengo un SQL Server 2005 que se ha vuelto impredecible últimamente, y me estoy rascando la cabeza por qué. Las consultas que se ejecutan en segundos cambian los planes y toman minutos (tomar el tiempo en el análisis completo de la tabla o en el spool de índice). Ahora, lo primero y más obvio es que las estadísticas son obsoletas, lo que hace que el optimizador se confunda, pero estoy convencido de que este no es el caso, en primer lugar porque los datos subyacentes no cambian significativamente (por ejemplo, agregar los datos de un día sobre los datos de un año ya en una tabla) y en segundo lugar porque las estadísticas de creación automática y las estadísticas de actualización automática son verdaderas. Sin embargo, el optimizador se está confundiendo; ejecutar el SQL en el Asesor de ajuste me da muchas CREATE STATISTICSdeclaraciones de varias columnas que parecen solucionarlo (hasta el siguiente bit de comportamiento incorrecto de SQL).

¿Alguna idea de una estrategia que pueda usar para abordar esta causa raíz? ¿Por qué las estadísticas "normales" no son suficientes?

Gayo
fuente

Respuestas:

8

Si su espera superior es SOS_SCHEDULER_YIELD, parecería que tiene algo de presión sobre la CPU. Pero esto podría ser el resultado de algo más, como que su diseño ya no sea suficiente para sus consultas. Sé que dijiste que solo estás agregando datos para un día, pero podrías haber llegado a un punto de inflexión.

¿Cómo se emiten sus consultas? ¿Es SQL dinámico? ¿Estás utilizando procedimientos almacenados? ¿Estás usando sp_executesql? ¿Es posible que tenga un caso de detección de parámetros? ¿Cómo es tu diseño de db? ¿Cuáles son las relaciones PK y FK?

¿Tienes un ejemplo de un buen plan? Si puede determinar un buen plan, puede usar guías de plan para forzar la ejecución de la consulta de una manera específica.

¿Puedes dar un ejemplo de un buen plan que salió mal?

Por último, vaya a buscar una copia de sp_whoIsActive ( http://whoisactive.com/ ) de Adam Machanic y úsela para determinar más sobre las consultas que se están ejecutando. Y si desea poder capturar la salida de sp_whoIsActive, vaya aquí http://www.littlekendra.com/2011/02/01/whoisactive/

SQLRockstar
fuente
Es una aplicación de terceros, no tengo control sobre su esquema o SQL, lo cual es bastante horrible, muchas consultas parametrizadas (por ejemplo where col=(cast @var...)) y @varpodrían serlo '%'. Lo heredé hace una o dos semanas y necesito mantenerlo funcionando básicamente hasta que se reemplace. Gracias por el enlace, le daré un giro.
Cayo
La siguiente mayor espera después SOS_SCHEDULER_YIELDfue CXPACKETy sp_configure "max degree of parallelism", 1parece haber, por ahora, golpeado ambos problemas en la cabeza. ¡Gracias!
Gaius
+1 para el enlace a sp_whoIsActive
Jeff
8

De MSDN :

"Las operaciones de inserción se producen en columnas clave ascendentes o descendentes Las estadísticas en columnas clave ascendentes o descendentes, como IDENTIDAD o columnas de marca de tiempo en tiempo real, pueden requerir actualizaciones estadísticas más frecuentes que las que realiza el optimizador de consultas. Las operaciones de inserción agregan nuevos valores a las columnas ascendentes o descendentes . El número de filas agregadas puede ser demasiado pequeño para activar una actualización de estadísticas. Si las estadísticas no están actualizadas y las consultas se seleccionan de las filas agregadas más recientemente, las estadísticas actuales no tendrán estimaciones de cardinalidad para estos nuevos valores. dar como resultado estimaciones de cardinalidad inexactas y un rendimiento de consulta lento.

Por ejemplo, una consulta que selecciona las fechas de pedidos de ventas más recientes tendrá estimaciones de cardinalidad inexactas si las estadísticas no se actualizan para incluir estimaciones de cardinalidad para las fechas de pedidos de ventas más recientes.

Después de las operaciones de mantenimiento Considere actualizar las estadísticas después de realizar procedimientos de mantenimiento que cambien la distribución de datos, como truncar una tabla o realizar una inserción masiva de un gran porcentaje de las filas. Esto puede evitar retrasos futuros en el procesamiento de consultas mientras las consultas esperan actualizaciones de estadísticas automáticas ".

Puede usar "EXEC sp_updatestats" de vez en cuando en su sistema (programado en algún momento) o usar la función STATS_DATE en todos los objetos y ver cuándo se actualizaron sus estadísticas la última vez y si hubo demasiado tiempo desde entonces, use UPDATE ESTADÍSTICAS para ese objeto en particular. En mi experiencia, incluso con las estadísticas automáticas habilitadas, todavía estamos obligados a actualizar las estadísticas de vez en cuando, debido a las operaciones de inserción que no activaron la actualización automática.

Para agregar mi código personal (usado en un trabajo semanal que construye declaraciones dinámicas para la actualización de estadísticas):

select distinct
        'update statistics [' + stats.SchemaName + '].[' + stats.TableName + ']'
            + case when stats.RowCnt > 50000 then ' with sample 30 percent;'
            else 
                ';' end
        as UpdateStatement
    from (
        select
            ss.name SchemaName,
            so.name TableName,
            so.id ObjectId,
            st.name AS StatsName, 
            STATS_DATE(st.object_id, st.stats_id) AS LastStatisticsUpdateDate
            , si.RowModCtr
            , (select case si2.RowCnt when 0 then 1 else si2.RowCnt end from sysindexes si2 where si2.id = si.id and si2.indid in (0,1)) RowCnt
        from sys.stats st
            join sysindexes si on st.object_id = si.id and st.stats_id = si.indid
            join sysobjects so on so.id = si.id and so.xtype = 'U' --user table
            join sys.schemas ss on ss.schema_id = so.uid
    ) stats
    where cast(stats.RowModCtr as float)/cast(stats.RowCnt as FLOAT)*100 >= 10 --more than 10% of the rows have changed
    or ( --update statistics that were not updated for more than 3 months (and rows no > 0)
        datediff(month, stats.LastStatisticsUpdateDate, getdate()) >= 3
        and stats.RowCnt > 0
    )

Aquí obtengo todos los objetos en los que no se actualizaron las estadísticas durante más de 3 meses o desde la última actualización de estadísticas, se modificó más del 10% de las filas.

Mariano
fuente
Hmm, mi principal evento de espera es SOS_SCHEDULER_YIELDpero no puedo decir en este momento si eso se debe a los malos planes, o si esta caja (de 6 años, 2 procesadores, 4G RAM) realmente está sobrecargada ahora y he pasado un punto de inflexión.
Gaius
en lugar de simplemente ejecutar esa consulta para hacer las declaraciones de ACTUALIZACIÓN y ejecutarlas manualmente, podría usar un cursor basado en esa declaración de selección para recorrer los resultados ejecutándolos usando llamadas a sp_executesql, de esa manera puede ejecutarlo automáticamente (por ejemplo, como parte de un plan de mantenimiento nocturno (u otro período de silencio)).
David Spillett
@David: esto es lo que estoy haciendo en el trabajo semanal :). Lo he formateado de manera diferente para que Gaius vea la salida que estoy usando. El guión inicial fue demasiado feo y largo. ¡Gracias por la ayuda con el formateo! ¿Me puede enviar a un tutorial de formato ... porque realmente no sé cómo hacer que el código se vea bien aquí. ¡Gracias!
Marian
hay un enlace de "ayuda para formatear" en la pantalla "editar respuesta", y como un icono a la derecha sobre el cuadro de respuesta inicial en la página principal de preguntas, que enumera la sintaxis de rebajas admitida por estos sitios.
David Spillett
3
Las estadísticas de actualización automática en realidad se disparan al 20% + 500 filas, no al 10%.
mrdenny
3

Supongo que una o más de sus tablas se están volviendo lo suficientemente grandes como para no alcanzar el 20% de los cambios necesarios para ayudar a marcar esas estadísticas actuales como obsoletas para que las Estadísticas de actualización automática entren en acción y, sin embargo, haya suficientes actualizaciones (o inserciones ) que tener estadísticas actualizadas ayudaría mucho. Encontré lo mismo recientemente en un entorno particular después de actualizar de SQL 2000 a SQL 2008.

Además de los otros sitios mencionados en las respuestas anteriores, sugeriría consultar los siguientes recursos en línea.

1) Red-Gate tiene una serie de libros electrónicos gratuitos disponibles para descargar, incluidos "SQL Server Statistics" de Holger Schmeling, donde encontrará la siguiente cita:

http://www.red-gate.com/our-company/about/book-store/

"las tablas con más de 500 filas al menos el 20% de los datos de una columna tuvieron que cambiarse para invalidar cualquier estadística vinculada"

2) SQL Sentry tiene una herramienta gratuita Plan Explorer que ayuda a rastrear problemas dentro de un plan SQL, como una estimación de demasiadas o muy pocas filas en comparación con el número real de filas para una tabla dada en una consulta. Simplemente guarde el plan de ejecución real de SSMS y luego recorra las diferentes partes del plan utilizando Plan Explorer. No es que la información no esté disponible en SSMS usando el plan de ejecución gráfico, pero la herramienta de SQL Sentry hace que sea mucho más fácil de ver.

http://www.sqlsentry.com/plan-explorer/sql-server-query-view.asp

3) Consulte la fecha de actualización de estadísticas usted mismo para ver las tablas en las consultas que más le interesen usando STATS_DATE (), puede encontrar una consulta rápida para obtener las estadísticas más antiguas utilizando una consulta que se encuentra en la siguiente discusión.

http://blog.sqlauthority.com/2010/01/25/sql-server-find-statistics-update-date-update-statistics/

¡Espero que esto ayude!

¡Creo que disfrutarás especialmente el libro de Red-Gate!

-Jeff

Jeff
fuente
Gracias, me abriré camino a través de esos. Soy principalmente un DBA de Oracle que heredó este sistema (aunque no tengo ningún prejuicio contra SQL Server en absoluto, por lo que veo desde 2005 es una plataforma muy capaz, simplemente no lo sé tan bien como lo sé de Oracle) .
Cayo