Ok, ich habe eine Abfrage für nicht gespeicherte Prozeduren, die wir in einem SSRS-Bericht verwenden. Diese Abfrage war höllisch langsam (ich hatte die ursprüngliche Version dieser Abfrage in den letzten zwei Stunden ausgeführt, immer noch nicht ausgeführt). Um sie zu verbessern, habe ich sie von Grund auf neu geschrieben und mir Folgendes ausgedacht:
Hier ist der langweilige Teil des Wortproblems:
Wir wollen eine Liste der ziehen TOP 5
Kunden pro Vertriebsmitarbeiter, aber ausschließen die TOP 10
Gesamt Kunden aus dieser Liste. (Wenn John Doe also Clients A, B, C, D und E hat und Client C zu den Top 10 gehört, ziehen Sie nur A, B, D und E.)
Um dies zu tun, verwendete die erste Abfrage ein IN (... NOT IN ( ) )
, also dachte ich, dass das Verschachteln von IN
das Problem war, um es umzuschreiben, tat ich ein OUTER APPLY
, das wirklich alles kaputt machte.
Wie auch immer, ich habe das alles behoben und die Abfrage ausgeführt, und es dauerte immer noch 10-15 Sekunden, von denen ich annahm, dass es sich um Parameter-Sniffing handelte. Zur Untersuchung habe ich die Abfrage in SSMS ausgeführt, hinzugefügt OPTION (RECOMPILE)
(um zu sehen, welcher Abfrageplan generiert wird) und Folgendes erhalten:
Es kann hier auf Brent Ozars 'Paste The Plan' angesehen werden . Die Abfrage, die dies generiert hat, war:
DECLARE @Top10Temp TABLE (Id INT)
INSERT INTO @Top10Temp
SELECT TOP 10 Id
FROM Object1
WHERE Column2 = @ReportId
AND Column3 = 0
GROUP BY Id
ORDER BY SUM(Column4 + Column5) DESC
SELECT Object2.*
FROM Object1 AS Object2
OUTER APPLY (
SELECT TOP 5
Object3.Id,
SUM(Object3.Column4 + Object3.Column5) AS Column6
FROM Object1 AS Object3
WHERE Object3.Column3 = 0
AND Object3.Column7 = Object2.Column7
AND Object3.Column2 = @ReportId
GROUP BY
Object3.Id
ORDER BY
SUM(Object3.Column4 + Object3.Column5) DESC
) AS Object4
WHERE Object2.Column2 = @ReportId
AND Object2.Column3 = 0
AND Object2.Id = Object4.Id
AND Object2.Id NOT IN (SELECT Id FROM @Top10Temp)
ORDER BY Object2.Column7
OPTION (RECOMPILE)
Jetzt hat die gleiche Abfrage aber mit OPTION (OPTIMIZE FOR UNKNOWN)
folgendem Plan generiert:
Was auch unter "Plan einfügen" angezeigt werden kann . Dieser Plan wurde in weniger als 1 Sekunde ausgeführt.
Wenn ich hinzufüge OPTION (OPTIMIZE FOR (@ReportId = #))
, wobei #
das gleiche wie die @ReportId
Variable ist, erhalte ich den gleichen Abfrageplan wie das zweite.
Habe ich etwas falsch gemacht? Ich habe Probleme zu verstehen, was passiert ist, daher werden alle Informationen sehr geschätzt. (Ich mag es auch nicht, den Optimierer über Hinweise zu beeinflussen, aber wenn es nötig ist, werde ich es behalten.)