Pourquoi ma requête est-elle soudainement plus lente qu'elle ne l'était hier?

76

[Salutations]

(Cochez une)

[ ] Well trained professional, [ ] Casual reader, [ ] Hapless wanderer,

J'ai un (cocher tout ce qui s'applique)

[ ] query [ ] stored procedure [ ] database thing maybe  

cela fonctionnait bien (le cas échéant)

[ ] yesterday [ ] in recent memory [ ] at some point 

mais est soudainement plus lent maintenant.

J'ai déjà vérifié pour m'assurer qu'il n'est pas bloqué et qu'il n'est pas victime d'une tâche de maintenance ou d'un rapport de longue durée, ni d'aucun autre processus hors bande.

Quel est le problème, que dois-je faire et quelles informations puis-je fournir pour obtenir de l'aide?

[*Insert appropriate closing remarks*]
Erik Darling
la source

Réponses:

88

Cher [ton nom ici]!

Oh non, je suis désolé d'entendre ça! Commençons par quelques notions de base pour vous permettre de vous préparer rapidement.

La chose que vous rencontrez s'appelle Parameter Sniffing

C'est un moyen de sortir de l'étrange problème étrange. Le nom sort de la langue. Comme le mot allemand pour écureuil.

Et c'est généralement ton ami.

Quand une requête frappe votre serveur, un plan doit être compilé. Pour économiser du temps et des ressources ultérieurement, un plan d'exécution est mis en cache en fonction du nombre estimé de lignes que le paramètre entraînera le traitement et le renvoi du code.

La meilleure façon d’imaginer ce qui ne va pas est d’imaginer une procédure stockée qui doit compter les éléments de deux populations déséquilibrées.

Par exemple:

  • Les personnes portant des chemises CrossFit qui ne sont pas blessées: Zero

  • Les personnes portant des chemises CrossFit qui grincent quand elles grincent: Tous

De toute évidence, une exécution de ce code nécessiterait beaucoup plus de travail qu'une autre, et les plans de requête que vous voudriez effectuer avec des quantités de travail totalement différentes sembleraient totalement différents.

Je suis contre quoi?

Il s'agit d'un problème réellement difficile à trouver, à tester et à résoudre.

  • C'est difficile à trouver car cela n'arrive pas toujours
  • Il est difficile à tester car vous devez savoir quels paramètres génèrent des plans différents.
  • C'est difficile à corriger, car il faut parfois régler les requêtes et les index.
  • Difficile à résoudre car il se peut que vous ne puissiez pas modifier les requêtes ou les index.
  • C'est difficile à corriger car même si vous modifiez des requêtes ou des index, il se peut que cela revienne

Réparations rapides

Parfois, tout ce dont vous avez besoin, c'est d'un peu de clarté. Ou plutôt, votre cache de plan le fait.

Si c'est une procédure stockée

Essayez de courir EXEC sys.sp_recompile @objname = N'schema.procname'. La procédure sera recompilée lors de la prochaine exécution d’un nouveau plan.

Qu'est-ce que cela ne résoudra pas:

  • Processus en cours d'exécution.

Qu'est-ce que cela ne garantit pas:

  • Le prochain processus exécuté après la recompilation utilisera un paramètre qui vous donnera un bon plan.

Vous pouvez également pointer sp_recompilesur une table ou une vue, mais sachez que tout le code qui touche cette table ou cette vue sera recompilé. Cela pourrait rendre le problème beaucoup plus difficile.

Si c'est une requête paramétrée

Votre travail est un peu plus difficile. Vous aurez besoin de localiser le SQL Handle. Vous ne voulez pas libérer la totalité du cache de plan - comme si vous utilisiez sp_recompileune table ou une vue, vous pourriez déclencher (ha ha ha) toute une série de conséquences inattendues.

Le moyen le plus simple de comprendre cette commande consiste à exécuter sp_BlitzWho *! Il existe une colonne appelée "correction de paramètre" qui contient une commande permettant de supprimer un seul plan du cache. Cela présente toutefois les mêmes inconvénients que la recompilation.

Qu'est-ce que cela ne résoudra pas:

  • Processus en cours d'exécution.

Qu'est-ce que cela ne garantit pas:

  • Le prochain processus exécuté après la recompilation utilisera un paramètre qui vous donnera un bon plan.

J'ai toujours besoin d'aide!

Nous allons avoir besoin des choses suivantes:

  • Le bon plan de requête, si possible
  • Le mauvais plan de requête
  • Les paramètres utilisés
  • La requête en question
  • Définitions de table et d'index

Obtention des plans de requête et de la requête

Si la requête est en cours d'exécution, vous pouvez utiliser sp_BlitzWho * ou sp_WhoIsActive pour capturer les requêtes en cours d'exécution.

EXEC sp_BlitzWho;

EXEC sp_WhoIsActive @get_plans = 1;

DES NOISETTES

Si la requête n'est pas en cours d'exécution, vous pouvez la vérifier dans le cache de plan à l'aide de sp_BlitzCache *.

Si vous utilisez SQL Server 2016+ et que Query Store est activé, vous pouvez utiliser sp_BlitzQueryStore *.

EXEC dbo.sp_BlitzCache @StoredProcName = 'Your Mom';

EXEC dbo.sp_BlitzQueryStore @StoredProcName = 'Your Mom';

Cela vous aidera à localiser la ou les versions en cache de votre procédure stockée. Si ce n'est que du code paramétré, votre recherche est un peu plus difficile. Cela peut aider, cependant:

EXEC dbo.sp_BlitzCache @QueryFilter = 'statement';

Vous devriez voir des résultats assez similaires de ceux-ci. Encore une fois, le plan de requête invitant la colonne Clicky bleu cool est votre ami.

DES NOISETTES

Le moyen le plus simple de partager des plans consiste à utiliser Paste The Plan * ou à vider le XML dans pastebin. Pour l'obtenir, cliquez sur l'une de ces colonnes invitant des cliques bleues. Votre plan de requête doit apparaître dans un nouvel onglet SSMS.

DES NOISETTES

Si vous souhaitez partager le code et les requêtes de votre entreprise, vous pouvez utiliser l'outil gratuit Plan Explorer de Sentry One pour anonymiser votre plan. N'oubliez pas que cela rend plus difficile l'obtention d'aide - le code anonymisé est beaucoup plus difficile à lire et à comprendre.

Tous les outils dont nous avons parlé doivent renvoyer le texte de la requête. Vous n'avez rien d'autre à faire ici.

Obtenir le (s) paramètre (s) est un peu plus difficile. Si vous utilisez Plan Explorer , un onglet situé en bas les répertorie pour vous.

DES NOISETTES

Si vous utilisez sp_BlitzCache *, il existe une colonne sur laquelle vous pouvez cliquer pour obtenir l’instruction d’exécution des procédures stockées.

DES NOISETTES

Obtenir les définitions de table et d'index

Vous pouvez facilement cliquer avec le bouton droit de la souris sur SSMS pour créer un script.

DES NOISETTES

Si vous souhaitez tout obtenir en un seul coup, sp_BlitzIndex * peut vous aider si vous le dirigez directement vers une table.

EXEC dbo.sp_BlitzIndex @DatabaseName = 'StackOverflow2010',
                       @SchemaName = 'dbo',
                       @TableName = 'Users';

Cela vous donnera la définition de la table (mais pas en tant qu'instruction create) et créera des instructions pour tous vos index.

La collecte et l’ajout de cette information à votre question devrait permettre aux gens d’avoir suffisamment d’informations pour vous aider ou vous orienter dans la bonne direction.

Je veux le faire moi-même!

Bien cool. Je suis content pour toi. Vous êtes fou.

Les gens pensent qu'ils «corrigent» le reniflage de paramètres de nombreuses manières:

Mais ceux-ci désactivent simplement le paramètre de détection de différentes manières. Cela ne veut pas dire qu'ils ne peuvent pas résoudre le problème, ils ne s'attaquent pas vraiment à la cause fondamentale.

C'est parce qu'il est généralement difficile de trouver la cause fondamentale. Vous devez rechercher ces "problèmes de qualité des plans" embêtants.

En commençant par les plans rapide vs lent, recherchez les différences telles que:

  • Index utilisés
  • Rejoindre la commande
  • Série vs parallèle

Recherchez également différents opérateurs qui rendent votre code sensible au reniflement de paramètres:

  • Des recherches
  • Trie
  • Type de jointure
  • Subventions mémoire (et par extension, déversements)
  • Bobines

Ne vous laissez pas emporter par la recherche, le scan, la fragmentation d'index ou tout ce que les gens cultivent dans le secteur du fret.

Généralement, il existe un problème d’indexation assez simple. Parfois, le code a besoin d'un peu de réécriture.

Si vous voulez en savoir plus sur le sniffing de paramètres:

Si vous lisez ceci et que vous pensez avoir manqué un lien ou un outil utile, laissez un commentaire. Je ferai de mon mieux pour le garder à jour.


Erik Darling
la source
28

La détection de paramètre n'est pas la seule cause possible des performances variables d'une requête. L'une des raisons courantes suivantes peut présenter les mêmes symptômes:

  1. Modification de la répartition / du volume des données, passage d'un point de basculement décisionnel de l'arbre de recherche de l'optimiseur
  2. Les index / fichiers se sont fragmentés
  3. Les statistiques ont été mises à jour / ajoutées / supprimées ou sont devenues obsolètes et trompeuses en raison de modifications des données
  4. L'utilisation de la mémoire Windows a changé
  5. Les journaux de transaction sont pleins et ne tronquent pas, ce qui entraîne une expansion répétée du fichier physique.
  6. Schéma modifié - index / vue indexée / colonne / contrainte ajoutée, modifiée ou supprimée, type de données modifié, etc.
  7. Paramètres d'indicateur de trace modifiés
  8. La mise à jour Windows a été appliquée
  9. Paramètre de base de données ou de serveur modifié
  10. Niveau de la CU du serveur modifié
  11. Paramètres de session de l'application client modifiés

Les points 6 à 11 de cette liste ne peuvent apparaître qu'après une action explicite. J'imagine que vous vouliez exclure ces éléments, mais souvent, celui qui relève le défi ne sait pas que quelqu'un d'autre a effectué des modifications et cela vaut la peine de vérifier avant de vous engager dans la procédure d'effacement des entrées du cache du plan.

SQLRaptor
la source
1
Merci pour l'édition Paul. @sp_BlitzErik - Je n'avais pas l'intention de donner des conseils sur des sujets spécifiques, mais simplement de faire prendre conscience de leur existence et de leur intérêt. Cela n’a aucunement pour but de diminuer votre excellent poste. Vous avez traité les paramètres de détection en profondeur, de manière professionnelle et avec bonne humeur. J'ai bien aimé le lire. Je veux seulement m'assurer que si quelqu'un ici visite ce message, après le titre accrocheur, il / elle est mis au courant des autres causes potentielles. IMHO cela ajoute de la valeur à votre message, mais si vous souhaitez toujours que je le supprime, faites-le moi savoir.
SQLRaptor
Non pas du tout. Je ne demanderais jamais à quelqu'un de supprimer une réponse incorrecte ou nuisible. Je pense toujours que vous pourriez ajouter quelques détails, mais c'est finalement à vous de décider.
Erik Darling
10

Pour ajouter aux réponses existantes au cas où elles ne vous aideraient pas, lorsque "soudainement" vos requêtes se comportent différemment le lendemain, vérifiez:

  • Le schéma des tables utilisées a-t-il changé depuis la dernière fois? Dans le cas de SSMS, vous pouvez cliquer avec le bouton droit de la souris sur le serveur dans l'explorateur d'objets et choisir Reports → Standard Reports → Schema Changes History.
  • Le nombre d'articles a-t-il augmenté de façon spectaculaire? Peut-être que votre requête est tellement plus lente quand il y a beaucoup de données dans les tables utilisées.
  • Est-ce que quelqu'un d'autre utilise la base de données en même temps que vous? Peut-être choisir des créneaux horaires où vous n'interférez pas avec le travail de l'autre.
  • À quoi ressemblent les statistiques du système? Peut-être que le serveur tourne à chaud et étrangle le processeur ou que les disques durs manquent d’espace ou de swap. Peut-être existe-t-il un autre problème matériel, tel qu'un incendie ou une inondation dans la salle des serveurs.
utilisateur1306322
la source
7

Une autre possibilité est que votre équipe d'infrastructure utilise des outils tels que vMotion sur VMware et que la machine virtuelle prenant en charge votre instance SQL soit déplacée de manière transparente d'hôte à hôte sans que l'administrateur de base de données ne soit au courant.

C'est un réel problème lorsque votre infrastructure est sous-traitée ... Je suis un vrai cauchemar.

pacreely
la source