web-dev-qa-db-fra.com

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

[Salutations]

(cochez une seule case)

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

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

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

qui 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, d'un rapport ou d'un autre processus hors bande de longue durée.

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

[*Insert appropriate closing remarks*]
77
Erik Darling

Cher [votre nom ici]!

Oh non, je suis désolé d'entendre ça! Commençons par quelques notions de base pour vous installer dans un Jiffy.

La chose que vous rencontrez s'appelle le reniflement des paramètres

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

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

Lorsqu'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 sur la base des lignes estimées, ce paramètre provoquera le traitement et le retour de votre code.

La façon la plus simple d'imaginer cette situation est d'imaginer une procédure stockée qui doit compter les choses 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 grimacent quand elles grimacent: Tous

De toute évidence, une exécution de ce code devrait faire beaucoup plus de travail qu'une autre, et les plans de requête que vous souhaitez effectuer des quantités de travail totalement différentes seraient totalement différents.

Je suis contre quoi?

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

  • C'est difficile à trouver car cela n'arrive pas de manière cohérente
  • C'est difficile à tester car vous devez savoir quels paramètres provoquent différents plans
  • Il est difficile à résoudre car il nécessite parfois un réglage des requêtes et des index
  • Il est difficile à résoudre car vous ne pourrez peut-être pas modifier les requêtes ou les index
  • Il est difficile à résoudre car même si vous modifiez des requêtes ou des index, il peut toujours revenir

Réparations rapides

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

S'il s'agit d'une procédure stockée

Essayez d'exécuter EXEC sys.sp_recompile @objname = N'schema.procname'. Cela entraînera la procédure de recompilation d'un nouveau plan lors de sa prochaine exécution.

Ce que cela ne résoudra pas:

  • Processus en cours d'exécution.

Ce que cela ne garantit pas:

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

Vous pouvez également pointer sp_recompile dans 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.

S'il s'agit d'une requête paramétrée

Votre travail est un peu plus difficile. Vous devrez retrouver la poignée SQL. Vous ne voulez pas libérer l'intégralité du cache du plan, tout comme l'utilisation de sp_recompile contre une table ou une vue, vous pourriez déclencher (ha ha ha) tout un tas de conséquences inattendues.

La façon la plus simple de comprendre cette commande est d'exécuter sp_BlitzWho *! Il y a une colonne appelée "correction des paramètres reniflant" qui a une commande pour supprimer un seul plan du cache. Cependant, cela présente les mêmes inconvénients que la recompilation.

Ce que cela ne résoudra pas:

  • Processus en cours d'exécution.

Ce que cela ne garantit pas:

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

J'ai encore 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 des tables et des 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;

NUTS

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

Si vous utilisez SQL Server 2016+ et que le magasin de requêtes est activé, vous pouvez utiliser sp_BlitzQueryStore *.

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

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

Ceux-ci vous aideront à retrouver les versions mises en cache de votre procédure stockée. Si c'est juste du code paramétré, votre recherche est un peu plus difficile. Cela peut aider, cependant:

EXEC dbo.sp_BlitzCache @QueryFilter = 'statement';

Vous devriez voir une sortie assez similaire de l'un d'eux. Encore une fois, le plan de requête invitant la colonne clicky bleu cool est votre ami.

NUTS

La façon la plus simple de partager des plans est d'utiliser Coller le plan *, ou de vider le XML dans Pastebin. Pour l'obtenir, cliquez sur l'une de ces colonnes bleues invitantes. Votre plan de requête doit apparaître dans un nouvel onglet SSMS.

NUTS

Si vous souhaitez partager le code et la requête de votre entreprise, vous pouvez utiliser l'outil gratuit Plan Explorer de Sentry One pour anonymiser votre plan. Gardez à l'esprit que cela rend plus difficile l'aide - le code anonymisé est beaucoup plus difficile à lire et à comprendre.

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

Obtenir le ou les paramètres est un peu plus difficile. Si vous utilisez Plan Explorer , il y a un onglet en bas qui les répertorie tous pour vous.

NUTS

Si vous utilisez sp_BlitzCache *, il y a une colonne cliquable qui vous donne l'instruction d'exécution pour les procédures stockées.

NUTS

Obtention des définitions de table et d'index

Vous pouvez facilement cliquer avec le bouton droit dans SSMS pour créer des scripts.

NUTS

Si vous voulez tout obtenir en une seule fois, sp_BlitzIndex * peut vous aider si vous le pointez directement sur 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 ces informations à votre question devraient permettre aux gens d'obtenir suffisamment d'informations pour vous aider ou vous orienter dans la bonne direction.

Je veux le faire moi-même!

Eh bien, cool. Je suis content pour toi. Vous fou.

Il existe de nombreuses façons dont les gens pensent qu'ils "corrigent" le reniflage des paramètres:

Mais ceux-ci désactivent simplement le reniflage de paramètres de différentes manières. Cela ne veut pas dire qu'ils ne peuvent pas résoudre le problème, ils ne parviennent tout simplement pas à la cause profonde.

En effet, il est généralement difficile de trouver la cause première. Vous devez rechercher ces embêtants "problèmes de qualité du plan".

En commençant par les plans rapides vs lents, recherchez des différences telles que:

  • Index utilisés
  • Rejoindre la commande
  • Serial vs Parallel

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

  • Recherches
  • Tris
  • Type de jointure
  • Octrois de mémoire (et par extension, déversements)
  • Bobines

Ne vous laissez pas trop emporter par la recherche vs le scan, la fragmentation de l'index ou tout autre truc culte des cargaisons que les gens ourlent.

Habituellement, il y a un problème d'indexation assez basique. Parfois, le code a besoin d'un peu de réécriture.

Si vous souhaitez en savoir plus sur le reniflage de paramètres:

Si vous lisez ceci et que vous pensez que j'ai raté un lien ou un outil utile, laissez un commentaire. Je ferai de mon mieux pour garder cela à jour.


89
Erik Darling

Le reniflage de paramètres 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. La distribution/le volume de données a changé, traversant un point de basculement de décision 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. Utilisation de la mémoire Windows modifiée
  5. Les journaux de transactions sont pleins et ne sont pas tronqués, provoquant une expansion répétée des fichiers physiques
  6. Schéma modifié - index/vue indexée/colonne/contrainte ajoutée, modifiée ou supprimée, type de données changé, etc.
  7. Paramètres de l'indicateur de trace modifiés
  8. La mise à jour Windows a été appliquée
  9. Modification de la base de données ou du serveur
  10. Le niveau CU du serveur a changé
  11. Les paramètres de session de l'application client ont été modifiés

Les éléments 6 à 11 de cette liste ne peuvent se produire qu'après une action explicite. Je suppose que vous vouliez les exclure, mais plusieurs fois celui qui rencontre le défi, n'est pas conscient que quelqu'un d'autre a apporté des modifications, et cela vaut la peine de vérifier avant de vous lancer sur la voie de la suppression des entrées de cache du plan.

27
SQLRaptor

Juste pour ajouter aux réponses existantes au cas où cela ne les aiderait 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 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.
  • Quelqu'un d'autre utilise-t-il la base de données en même temps que vous? Choisissez peut-être des plages 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 fonctionne à chaud et limite le processeur ou que les disques durs sont à court d'espace ou d'échange. Il y a peut-être un autre problème matériel comme un incendie ou une inondation dans la salle des serveurs.
9
user1306322

Une autre possibilité est que votre équipe d'infrastructure utilise des outils tels que vMotion sur VMware et le VM qui prend en charge votre instance SQL est déplacé de manière transparente d'hôte à hôte sans que le DBA le sache).

C'est un vrai problème lorsque votre infrastructure est externalisée ... je fais un vrai cauchemar avec elle.

7
pacreely