Antworten:
Die Antwort liegt, wie immer (meistens), im Ausführungsplan.
Es gibt bestimmte Operatoren, bei denen alle Zeilen ankommen müssen, bevor sie diese Zeilen verarbeiten und weiterleiten können. Beispiel:
Sie werden entweder als Blockierungs- oder Stop-and-Go-Operatoren bezeichnet. Sie werden häufig ausgewählt, wenn das Optimierungsprogramm denkt, dass es eine ganze Menge Daten verarbeiten muss, um Ihre Daten zu finden.
Es gibt andere Operatoren, die in der Lage sind, Streams zu starten oder gefundene Zeilen sofort weiterzuleiten
Wenn Abfragen beginnen, Daten sofort zurückzugeben, aber nicht sofort beendet werden, ist dies in der Regel ein Zeichen dafür, dass das Optimierungsprogramm einen Plan zum schnellen Suchen und Zurückgeben einiger Zeilen mithilfe von Operatoren mit geringeren Startkosten ausgewählt hat.
Dies kann aufgrund von Zeilenzielen geschehen, die entweder von Ihnen oder vom Optimierer eingeführt wurden.
Es kann auch vorkommen, dass aus irgendeinem Grund ein falscher Plan ausgewählt wird (mangelnde SARGability, Parameter-Sniffing, unzureichende Statistiken usw.), dies erfordert jedoch mehr Zeit, um dies herauszufinden.
Weitere Informationen finden Sie in Rob Farleys Blog hier
Und Paul Whites Serie über Reihentore hier , hier , hier und hier .
Wenn Sie von SSMS sprechen, sollten Sie auch beachten, dass Zeilen nur dann angezeigt werden, wenn ein ganzer Puffer gefüllt wurde, und nicht nur zufällig.
Wenn ich verstehe, was Sie beobachten, ist dies, wie Management Studio Zeilen rendert , und hat wenig damit zu tun, wie SQL Server Zeilen zurückgibt . Tatsächlich kann SSMS oft nicht mithalten, wenn Sie große Ergebnisse an SSMS zurückgeben und versuchen, sie in einem Raster zu rendern, und SQL Server wartet darauf, dass die App weitere Zeilen verarbeitet. In diesem Fall wird SQL Server ASYNC_NETWORK_IO
Wartezeiten ansammeln .
Sie können dies ein wenig steuern, indem Sie "Ergebnisse in Text" anstelle von "Ergebnisse in Raster" verwenden, da SSMS Text schneller zeichnen kann als Gitter. Dies kann sich jedoch wahrscheinlich auf die Lesbarkeit auswirken, abhängig von der Anzahl der Spalten und den beteiligten Datentypen. Beides wird beeinflusst, wenn SSMS beschließt, die Ergebnisse tatsächlich in diesen Bereich zu schreiben. Dies hängt davon ab, wie voll der Ausgabepuffer ist.
Wenn Sie über mehrere Anweisungen verfügen und den Puffer zwingen möchten, die Ausgabeergebnisse im Nachrichtenfenster wiederzugeben, können Sie zwischen den Anweisungen einen kleinen Drucktrick anwenden:
RAISERROR('', 0, 1) WITH NOWAIT;
Dies hilft jedoch nicht, wenn Sie SSMS dazu bringen möchten, Zeilen schneller zu rendern, wenn die gesamte Ausgabe von einer einzelnen Anweisung stammt.
Sie können dies direkt steuern, indem Sie die Anzahl der in SSMS gerenderten Ergebnisse begrenzen. Ich sehe oft Leute, die sich darüber beschweren, wie lange es dauert, bis eine Million Zeilen wieder im Raster sind. Was um alles in der Welt jeder mit einer Million Zeilen in einem SSMS-Grid machen wird, weiß ich nicht.
Es gibt einige Hacks wie OPTION (FAST 100)
, die für das Abrufen dieser ersten 100 Zeilen (oder aller 100 Zeilen, wenn es keine äußeren gibt ORDER BY
) optimiert sind , aber dies kann zu Lasten eines viel langsameren Abrufs für den Rest der Zeilen und eines Plans gehen, der mehr ist Insgesamt ineffizient, ist also meiner Meinung nach keine gute Wahl.
Ihre Frage bezieht sich nicht auf SQLServer per se, sondern auf:
Gibt es eine Möglichkeit, dies zu kontrollieren?
Kurze Antwort :
sqlcmd
anstelle von ssms
odersqlcmd
-Modus vonssms
Lange Antwort :
Na sicher! Aber nicht eins - wahrscheinlich
sqlcmd
oder in aussqlcmd
im -Modus in ssms aus.spid
und Sie erhalten eine vollständige Liste der Sitzungseinstellungen. Vergleiche mit den Einstellungen der sqlcmd
Sitzung. Wenn nichts klickt - kopieren Sie alle Sitzungseinstellungen aus dem Profiler in Ihr Abfrageskript, führen Sie im sqlcmd
-Modus aus und ändern Sie die Einstellungen nach und nach, um den Schuldigen zu finden.Viel Glück!
Um die Antwort von sp_BlitzErik zu ergänzen, verwenden Sie das Beispiel a NOT IN ()
mit einer Unterauswahl. Um festzustellen, ob sich ein Element im Ergebnis der verschachtelten Abfrage befindet, muss (im Allgemeinen) das gesamte Ergebnis abgerufen werden.
Eine einfache Möglichkeit, die Leistung solcher Abfragen zu verbessern, besteht darin, sie als " LEFT OUTER JOIN
where condition for RIGHT
side" (null) umzuschreiben (Sie könnten es natürlich umdrehen, aber wer verwendet es RIGHT OUTER JOINS
?). Auf diese Weise können die Ergebnisse sofort wieder angezeigt werden.
WHERE t.x IN (<complex SELECT subquery>)
der entsprechende LEFT JOIN, überprüft wird LEFT JOIN (<complex SELECT subquery>) AS r ON r.x = t.x .... WHERE r.x IS NULL
, muss auch die Unterabfrage ausgewertet werden (also derselbe komplexe Plan mit dem NOT IN-Version).
NOT EXISTS
aber Oracle NOT IN
bei Abfragen. Aber heute muss es als Fehler im Plan Generator betrachtet werden