web-dev-qa-db-fra.com

SQL Server Performance Dégradation soudaine

J'ai un serveur SQL 2005 qui est devenu imprévisible de retard, et je me gratte la tête de la raison pour laquelle. Les requêtes qui exécutées en secondes changent de plans et prennent des minutes (prenant le temps en table de table entière ou la bobine d'index). Maintenant, la première et la plus évidente est, les statistiques sont obsolètes causant l'optimiseur de se confondre, mais je suis convaincu que cela n'est pas le cas - d'abord parce que les données sous-jacentes ne changent pas de manière significative (par exemple, ajouter une journée de données sur les données d'un jour des données Déjà dans une table) et deuxièmement, car la création automatique de statistiques et de statistiques de mise à jour automatique sont à la fois vraies. Cependant, l'optimiseur est devenir confus; Courir SQL dans le Tuning Advisor me donne beaucoup de multi-colonnes CREATE STATISTICS Les déclarations qui semblent résoudre (jusqu'au prochain bit de mauvaise conduite SQL).

Des idées d'une stratégie que je peux utiliser pour aborder la racine - causant cela? Pourquoi les statistiques "normales" ne sont-elles pas suffisantes?

13
Gaius

Si votre top attendez est sos_scheduler_yield, il apparaîtrait que vous avez une pression sur la CPU. Mais cela pourrait être le résultat de quelque chose d'autre, tel que votre conception ne suffisant plus pour vos questions. Je sais que vous avez dit que vous n'avez qu'ajouter une journée de données d'une journée, mais vous auriez pu frapper un point de basculement.

Comment les requêtes sont-elles émises? Est-ce dynamique SQL? Utilisez-vous des procédures stockées? Utilisez-vous sp_executesql? Est-il possible que vous ayez un cas de paramètre reniflant? À quoi ressemble votre conception de DB? Quels 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 la requête à exécuter de manière spécifique.

Pouvez-vous donner un exemple d'un bon plan disparu?

Enfin, allez prendre une copie de sp_whoisactive ( http://whoisacactive.com/ ) d'Adam Machanic et utilisez-le pour en déterminer plus sur les requêtes qui fonctionnent. Et si vous voulez pouvoir capturer la sortie de sp_whoisactive, allez ici http://www.litttittittkendra.com/2011/02/01/whoisactive/

8
SQLRockstar

De - MSDN :

" Les opérations d'insertion se produisent sur des colonnes de touches ascendantes ou décroissantes Statistiques sur les colonnes de clé ascendantes ou décroissantes, telles que les colonnes d'horodatage d'identité ou d'horodatage en temps réel, peuvent nécessiter plus fréquemment. mises à jour des statistiques que l'optimisation de la requête effectue. Insérer les opérations appendez de nouvelles valeurs aux colonnes ascendantes ou décroissantes. 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 ne sont pas à jour. Des lignes ajoutées, les statistiques actuelles n'auront pas d'estimations de cardinalité pour ces nouvelles valeurs. Cela peut entraîner des estimations de cardinalité inexactes et des performances de requête lentes.

Par exemple, une requête qui sélectionne à partir des dernières dates de commande de vente aura des estimations de cardinalité inexactes si les statistiques ne sont pas mises à jour pour inclure des estimations de cardinalité pour les dernières dates de commande de vente.

Après les opérations de maintenance envisagez la mise à jour des 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 vrac d'un pourcentage élevé de les rangées. Cela peut éviter les retards futurs dans le traitement de la requête tandis que les requêtes attendent les mises à jour de statistiques automatiques. "

Vous pouvez utiliser "EXEC SP_UPDATESTATS" de temps en temps sur votre système (planifié quelque temps) ou utiliser la fonction STATS_DATE sur tous les objets et voir lorsque leurs statistiques ont été mises à jour la dernière fois et s'il y avait trop de temps depuis lors, utilisez la mise à jour. Statistiques pour cet objet particulier. Dans mon expérience, même avec des statistiques automatiques activées, nous sommes toujours obligés de mettre à jour des statistiques de temps en temps, en raison de l'insertion des opérations qui n'ont pas déclenché la mise à jour automatique.

Pour ajouter mon code personnel (utilisé dans un emploi hebdomadaire qui construit 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 où il n'y avait pas de statistiques mis à jour pour plus de 3 mois ou depuis la mise à jour de la dernière statistique, plus de 10% des lignes ont changé.

8
Marian