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:
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_recompile
sur 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_recompile
une 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;
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.
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.
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.
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.
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.
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.