Contexte
J'ai une requête en cours d'exécution sur SQL Server 2008 R2 qui joint et / ou joint à gauche environ 12 "tables" différentes. La base de données est assez volumineuse avec de nombreuses tables de plus de 50 millions de lignes et environ 300 tables différentes. C'est pour une grande entreprise qui a 10 entrepôts à travers le pays. Tous les entrepôts lisent et écrivent dans la base de données. Donc, c'est assez grand et pas mal occupé.
La requête avec laquelle j'ai des problèmes ressemble à ceci:
select t1.something, t2.something, etc.
from Table1 t1
inner join Table2 t2 on t1.id = t2.t1id
left outer join (select * from table 3) t3 on t3.t1id = t1.t1id
[etc]...
where t1.something = 123
Notez que l'une des jointures se trouve sur une sous-requête non corrélée.
Le problème est que, à compter de ce matin, sans aucune modification (que je ne connais pas d’aucune personne de mon équipe), la requête, qui prend généralement environ 2 minutes, a pris une heure et demie - quand elle couru du tout. Le reste de la base de données est très bien. J'ai retiré cette requête du sproc dans lequel elle s'exécute habituellement et je l'ai exécutée dans SSMS avec des variables de paramètre codées en dur avec la même lenteur.
L'étrangeté est que lorsque je prends la sous-requête non corrélée et la jette dans une table temporaire, puis que je l'utilise au lieu de la sous-requête, la requête s'exécute correctement. Aussi (et c'est le plus étrange pour moi) si j'ajoute ce morceau de code à la fin de la requête, la requête est géniale:
and t.name like '%'
J'ai conclu (peut-être à tort) de ces petites expériences que la raison du ralentissement est due à la manière dont le plan d'exécution mis en cache de SQL est configuré: lorsque la requête est un peu différente, elle doit créer un nouveau plan d'exécution.
Ma question est la suivante: lorsqu'une requête qui fonctionnait rapidement auparavant commence soudainement à fonctionner lentement au milieu de la nuit et que rien d'autre n'est affecté à l'exception de cette requête, comment puis-je résoudre le problème et comment l'empêcher de se reproduire à l'avenir ? Comment savoir ce que SQL fait en interne pour le ralentir (si la mauvaise requête s'exécute, je peux obtenir son plan d'exécution mais il ne s'exécutera pas - le plan d'exécution attendu pourrait peut-être me donner quelque chose?)? Si ce problème concerne le plan d'exécution, comment empêcher SQL de penser que des plans d'exécution vraiment merdiques sont une bonne idée?
De plus, ce n'est pas un problème avec le reniflage de paramètres. Je l'ai déjà vu auparavant, et ce n'est pas le cas, car même lorsque je code les variables dans SSMS, les performances sont lentes.