Hintergrund
Ich habe eine Abfrage für SQL Server 2008 R2, die ungefähr 12 verschiedene "Tabellen" verknüpft und / oder links verknüpft. Die Datenbank ist mit vielen Tabellen über 50 Millionen Zeilen und ungefähr 300 verschiedenen Tabellen ziemlich groß. Es ist für ein großes Unternehmen, das 10 Lager im ganzen Land hat. Alle Lagerhäuser lesen und schreiben in die Datenbank. Es ist also ziemlich groß und ziemlich beschäftigt.
Die Abfrage, mit der ich Probleme habe, sieht ungefähr so aus:
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
Beachten Sie, dass sich einer der Joins in einer nicht korrelierten Unterabfrage befindet.
Das Problem ist, dass ab heute Morgen, ohne dass Änderungen (die ich oder jemand aus meinem Team kennen) am System vorgenommen wurden, die Abfrage, deren Ausführung normalerweise etwa 2 Minuten dauert, anderthalb Stunden in Anspruch nimmt lief überhaupt. Der Rest der Datenbank summt prima mit. Ich habe diese Abfrage aus dem Sproc genommen, in dem sie normalerweise ausgeführt wird, und ich habe sie in SSMS mit fest codierten Parametervariablen mit derselben Langsamkeit ausgeführt.
Das Seltsame ist, dass, wenn ich die nicht korrelierte Unterabfrage nehme und sie in eine temporäre Tabelle wirfe und dann diese anstelle der Unterabfrage verwende, die Abfrage einwandfrei ausgeführt wird. Auch (und das ist das seltsamste für mich), wenn ich diesen Code am Ende der Abfrage anhänge, läuft die Abfrage großartig:
and t.name like '%'
Ich bin aus diesen kleinen Experimenten (möglicherweise falsch) zu dem Schluss gekommen, dass der Grund für die Verlangsamung darin liegt, wie der zwischengespeicherte Ausführungsplan von SQL eingerichtet ist. Wenn die Abfrage ein wenig anders ist, muss ein neuer Ausführungsplan erstellt werden.
Meine Frage lautet: Wenn eine Abfrage, die früher plötzlich schnell lief, mitten in der Nacht langsam ausgeführt wird und nichts anderes als diese eine Abfrage betroffen ist, wie behebe ich sie und wie verhindere ich, dass sie in Zukunft ausgeführt wird ? Woher weiß ich, was SQL intern tut, um es so langsam zu machen? (Wenn die fehlerhafte Abfrage ausgeführt wird, kann ich den Ausführungsplan abrufen, aber er wird nicht ausgeführt. Vielleicht gibt mir der erwartete Ausführungsplan etwas?) Wie halte ich SQL davon ab, wirklich beschissene Ausführungspläne für eine gute Idee zu halten, wenn dieses Problem mit dem Ausführungsplan zusammenhängt?
Dies ist auch kein Problem beim Parameter-Sniffing. Ich habe das schon einmal gesehen, und das ist es nicht, denn selbst wenn ich die Variablen in SSMS hart codiere, bekomme ich immer noch eine langsame Leistung.