Dégradation soudaine des performances de SQL Server

13

J'ai un SQL Server 2005 qui est devenu imprévisible ces derniers temps, et je me gratte la tête pour savoir pourquoi. Les requêtes qui s'exécutent en quelques secondes changent de plan et prennent quelques minutes (en prenant le temps dans l'analyse complète de la table ou le spouleur d'index). Maintenant, la première chose et la plus évidente est que les statistiques sont obsolètes, ce qui provoque la confusion de l'optimiseur, mais je suis convaincu que ce n'est pas le cas - tout d'abord parce que les données sous-jacentes ne changent pas de manière significative (par exemple, ajouter des données d'une journée au-dessus des données d'une année déjà dans un tableau) et deuxièmement parce que les statistiques de création automatique et les statistiques de mise à jour automatique sont toutes deux vraies. Cependant l'optimiseur est de se confondre; exécuter le SQL dans le Tuning Advisor me donne beaucoup d' CREATE STATISTICSinstructions multi-colonnes qui semblent le corriger (jusqu'à ce que le bit suivant de SQL se comporte mal).

Des idées de stratégie que je peux utiliser pour aborder l'origine de cela? Pourquoi les statistiques "normales" ne sont-elles pas suffisantes?

Gaius
la source

Réponses:

8

Si votre attente supérieure est SOS_SCHEDULER_YIELD, il semblerait que vous ayez une certaine pression sur le processeur. Mais cela pourrait être le résultat de quelque chose d'autre, tel que votre conception ne suffit plus pour vos requêtes. Je sais que vous avez dit que vous ajoutez seulement une journée de données, mais vous pourriez avoir atteint un point de basculement.

Comment sont émises vos requêtes? Est-ce du SQL dynamique? Utilisez-vous des procédures stockées? Utilisez-vous sp_executesql? Est-il possible que vous ayez un cas de reniflage de paramètres? À quoi ressemble votre design db? Quelles sont les relations PK et FK?

Avez-vous un exemple de bon plan? Si vous êtes en mesure de déterminer un bon plan, vous pouvez utiliser des guides de plan pour forcer l'exécution de la requête d'une manière spécifique.

Pouvez-vous donner un exemple d'un bon plan qui a mal tourné?

Enfin, allez récupérer une copie de sp_whoIsActive ( http://whoisactive.com/ ) d'Adam Machanic et utilisez-le pour en savoir plus sur les requêtes en cours d'exécution. Et si vous voulez pouvoir capturer la sortie de sp_whoIsActive, allez ici http://www.littlekendra.com/2011/02/01/whoisactive/

SQLRockstar
la source
C'est une application tierce, je n'ai aucun contrôle sur son schéma ou SQL, ce qui est assez horrible, beaucoup de requêtes paramétrées (par exemple where col=(cast @var...)) et @varpourraient l'être '%'. Je l'ai hérité il y a une semaine ou deux, et je dois le faire fonctionner jusqu'à ce qu'il soit remplacé. Merci pour le lien, je vais lui faire un tourbillon.
Gaius
La prochaine plus grande attente a SOS_SCHEDULER_YIELDété CXPACKETet sp_configure "max degree of parallelism", 1semble avoir - pour l'instant - frappé les deux problèmes. Merci!
Gaius
+1 pour le lien vers sp_whoIsActive
Jeff
8

Depuis MSDN :

"Les opérations d'insertion se produisent sur des colonnes clés ascendantes ou descendantes. Les statistiques sur les colonnes clés ascendantes ou descendantes, telles que IDENTITY ou les colonnes d'horodatage en temps réel, peuvent nécessiter des mises à jour des statistiques plus fréquentes que celles effectuées par l'optimiseur de requêtes. Les opérations d'insertion ajoutent de nouvelles valeurs aux colonnes ascendantes ou descendantes. . Le nombre de lignes ajoutées peut être trop petit pour déclencher une mise à jour des statistiques. Si les statistiques ne sont pas à jour et que les requêtes sont sélectionnées à partir des dernières lignes ajoutées, les statistiques actuelles n'auront pas d'estimation de cardinalité pour ces nouvelles valeurs. Cela peut entraînent des estimations de cardinalité inexactes et des performances de requête lentes.

Par exemple, une requête qui sélectionne parmi les dates de commande client les plus récentes aura des estimations de cardinalité inexactes si les statistiques ne sont pas mises à jour pour inclure des estimations de cardinalité pour les dates de commande client les plus récentes.

Après les opérations de maintenance Envisagez de mettre à jour les statistiques après avoir effectué des procédures de maintenance qui modifient la distribution des données, telles que tronquer une table ou effectuer une insertion en bloc d'un grand pourcentage des lignes. Cela peut éviter de futurs retards dans le traitement des requêtes pendant que les requêtes attendent les mises à jour automatiques des statistiques. "

Vous pouvez utiliser "EXEC sp_updatestats" de temps en temps sur votre système (prévu un certain temps) ou utiliser la fonction STATS_DATE sur tous les objets et voir quand leurs statistiques ont été réellement mises à jour la dernière fois et s'il y a trop de temps depuis lors, utilisez UPDATE STATISTIQUES pour cet objet particulier. D'après mon expérience, même avec les statistiques automatiques activées, nous sommes toujours obligés de mettre à jour les statistiques de temps en temps, en raison des opérations d'insertion qui n'ont pas déclenché la mise à jour automatique.

Pour ajouter mon code personnel (utilisé dans un travail hebdomadaire qui crée des instructions dynamiques pour la mise à jour des statistiques):

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
    )

Ici, je reçois tous les objets pour lesquels les statistiques n'ont pas été mises à jour depuis plus de 3 mois ou depuis la dernière mise à jour des statistiques, plus de 10% des lignes ont été modifiées.

Marian
la source
Hmm, mon principal événement d'attente est SOS_SCHEDULER_YIELDmais je ne peux pas dire pour l'instant si cela est dû aux mauvais plans, ou si cette boîte (6 ans, 2 processeurs, RAM 4G) est vraiment juste surchargée maintenant et j'ai dépassé un point de basculement.
Gaius
plutôt que de simplement exécuter cette requête pour créer les instructions UPDATE et les exécuter manuellement, vous pouvez utiliser un curseur basé sur cette instruction select pour boucler les résultats en les exécutant à l'aide d'appels à sp_executesql - de cette façon, vous pouvez l'exécuter automatiquement (par exemple en tant que partie d'un plan d'entretien pendant la nuit (ou autre période de calme)).
David Spillett
@David: c'est ce que je fais dans le travail hebdomadaire :). Je viens de le formater différemment pour que Gaius voie la sortie que j'utilise. Le script initial était beaucoup trop laid et long. Merci pour l'aide au formatage! Pouvez-vous m'envoyer à un tutoriel de mise en forme ... parce que je ne sais pas vraiment comment rendre le code joli ici. Merci!
Marian
il y a un lien "aide à la mise en forme" sur l'écran "modifier la réponse", et sous forme d'icône à droite au-dessus de la boîte de réponse initiale sur la page principale des questions, qui répertorie la syntaxe de démarque prise en charge par ces sites.
David Spillett
3
Les statistiques de mise à jour automatique se déclenchent réellement à 20% + 500 lignes, et non à 10%.
mrdenny
3

Je suppose qu'une ou plusieurs de vos tables deviennent suffisamment grandes pour ne pas atteindre les 20% des modifications nécessaires pour aider à marquer ces statistiques actuelles comme périmées afin que les statistiques de mise à jour automatique démarrent et pourtant il y a suffisamment de mises à jour (ou insertions) ) que la mise à jour des statistiques aiderait beaucoup. J'ai trouvé la même chose récemment dans un environnement particulier après la mise à niveau de SQL 2000 vers SQL 2008.

En plus des autres sites mentionnés dans les réponses ci-dessus, je suggère de consulter les ressources en ligne suivantes.

1) Red-Gate a un certain nombre d'ebooks gratuits disponibles en téléchargement, y compris "SQL Server Statistics" par Holger Schmeling, où vous trouverez la citation suivante:

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

"les tables contenant plus de 500 lignes, au moins 20% des données d'une colonne ont dû être modifiées afin d'invalider les statistiques liées"

2) SQL Sentry dispose d'un outil gratuit d'Explorateur de plans qui permet de suivre les problèmes dans un plan SQL, tels qu'une estimation de trop ou trop peu de lignes par rapport au nombre réel de lignes pour une table donnée dans une requête. Enregistrez simplement le plan d'exécution réel à partir de SSMS, puis parcourez les différentes parties du plan à l'aide de Plan Explorer. Ce n'est pas que les informations ne sont pas disponibles dans SSMS à l'aide du plan d'exécution graphique, mais l'outil de SQL Sentry le rend beaucoup plus facile à voir.

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

3) Vérifiez vous-même la date de mise à jour des statistiques pour les tableaux dans les requêtes qui vous intéressent le plus en utilisant STATS_DATE (), vous pouvez trouver une requête rapide pour obtenir les statistiques les plus anciennes en utilisant une requête trouvée dans la discussion suivante.

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

J'espère que ça aide!

Je pense que vous apprécierez particulièrement le livre de Red-Gate!

-Jeff

Jeff
la source
Merci, je vais travailler à travers ceux-ci. Je suis principalement un DBA Oracle qui a hérité de ce système (même si je n'ai aucun préjugé contre SQL Server, d'après ce que je vois depuis 2005, c'est une plate-forme très performante, je ne le connais pas aussi bien que je connais Oracle) .
Gaius