Meine Frage ist, wie SQL Server mit einer Abfrage umgeht, die mehr Datenvolumen in den Puffercache ziehen muss, als Speicherplatz verfügbar ist. Diese Abfrage würde mehrere Verknüpfungen enthalten, sodass die Ergebnismenge in diesem Format noch nicht auf der Festplatte vorhanden ist und die Ergebnisse kompiliert werden müssten. Aber auch nach der Kompilierung wird immer noch mehr Speicherplatz benötigt, als im Puffercache verfügbar ist.
Ich werde ein Beispiel geben. Angenommen, Sie haben eine SQL Server-Instanz mit insgesamt 6 GB Puffer-Cache-Speicherplatz. Ich führe eine Abfrage mit mehreren Verknüpfungen aus, die 7 GB Daten liest. Wie kann SQL Server auf diese Anforderung antworten? Speichert es die Daten vorübergehend in Tempdb? Scheitert es? Tut es etwas, das nur Daten von der Festplatte liest und Segmente gleichzeitig kompiliert?
Was passiert außerdem, wenn ich versuche, 7 GB Gesamtdaten zurückzugeben? Ändert sich dadurch, wie SQL Server damit umgeht?
Ich kenne bereits mehrere Möglichkeiten, um dies zu beheben. Ich bin nur gespannt, wie SQL Server diese Anforderung intern verarbeitet, wenn sie wie angegeben ausgeführt wird.
Ich bin mir auch sicher, dass diese Informationen irgendwo vorhanden sind, aber ich konnte sie nicht finden.
Antworten:
Seiten werden nach Bedarf in den Speicher eingelesen. Wenn kein freier Speicher verfügbar ist, wird die älteste nicht geänderte Seite durch die eingehende Seite ersetzt.
Wenn Sie also eine Abfrage ausführen, für die mehr Daten erforderlich sind, als in den Speicher passen, haben viele Seiten eine sehr kurze Lebensdauer im Speicher, was zu vielen E / A führt.
Sie können diesen Effekt sehen, indem Sie den Zähler "Page Life Expectancy" im Windows Performance Monitor anzeigen. Unter https://sqlperformance.com/2014/10/sql-performance/knee-jerk-page-life-expectancy finden Sie einige wichtige Details zu diesem Zähler.
In den Kommentaren haben Sie speziell gefragt, was passiert, wenn die Ergebnisse der Abfrage größer als der verfügbare Pufferplatz sind. Nehmen Sie das einfachste Beispiel: Nehmen Sie
select * from some_very_big_table;
an, die Tabelle hat 32 GB undmax server memory (MB)
ist auf 24 GB konfiguriert. Alle 32 GB Tabellendaten werden in die Seiten in den Seitenpuffer einer nach dem anderen gelesen werden, verriegelt, in Netzwerkpakete formatiert und über das Kabel gesendet. Dies geschieht Seite für Seite; Es könnten 300 solcher Abfragen gleichzeitig ausgeführt werden. Unter der Annahme, dass keine Blockierung stattgefunden hat, werden die Daten für jede Abfrage Seite für Seite in den Seitenpufferbereich eingelesen und so schnell wie möglich auf den Draht gelegt Daten anfordern und verbrauchen. Sobald alle Daten von jeder Seite auf die Leitung gesendet wurden, wird die Seite entriegelt und sehr schnell durch eine andere Seite von der Festplatte ersetzt.Bei einer komplexeren Abfrage, beispielsweise beim Aggregieren von Ergebnissen aus mehreren Tabellen, werden Seiten genau wie oben beschrieben in den Speicher gezogen, wie sie vom Abfrageprozessor benötigt werden. Wenn der Abfrageprozessor temporären Arbeitsbereich benötigt, um die Ergebnisse zu berechnen, weiß er dies im Voraus, wenn er einen Plan für die Abfrage erstellt, und fordert Arbeitsbereich (Speicher) von SQLOS an . SQLOS wird irgendwann (vorausgesetzt, es tritt keine Zeitüberschreitung auf ) dem Abfrageprozessor diesen Speicher gewähren. Ab diesem Zeitpunkt wird die Abfrageverarbeitung fortgesetzt . Wenn der Abfrageprozessor einen Fehler bei der Schätzung macht, wie viel Speicher von SQLOS angefordert werden muss, muss er möglicherweise einen "Spill to Disk" durchführen.Operation, bei der Daten vorübergehend in einer Zwischenform in Tempdb geschrieben werden. Die Seiten, die in Tempdb geschrieben wurden, werden entsperrt, sobald sie in Tempdb geschrieben wurden, um Platz für das Einlesen anderer Seiten in den Speicher zu schaffen. Schließlich kehrt der Abfrageprozess zu den in tempdb gespeicherten Daten zurück und paginiert diese bei Verwendung von Latching in Seiten im Puffer, die als frei markiert sind.
Ich vermisse zweifellos eine Menge sehr technischer Details in der obigen Zusammenfassung, aber ich denke, das erfasst die Essenz, wie SQL Server mehr Daten verarbeiten kann, als in den Speicher passen.
quelle
Ich kann nicht genau sagen, was Ihre Abfrage in diesem Szenario tun würde, aber SQL Server bietet verschiedene Optionen, je nachdem, wie viel benötigt wird.
Der beste Weg, um herauszufinden, was passieren würde, besteht darin, das Szenario in einer Entwicklungsumgebung zu erstellen und herauszufinden.
quelle
Um diesen speziellen Teil zu beantworten, möchte ich Ihnen sagen, wie dies verwaltet wird. Die Seiten haben eine Größe von 8 KB. Wenn Sie eine Abfrage ausführen, die einen großen Datensatz anfordert und für die zahlreiche Seiten in den Speicher gebracht werden müssen, werden von SQL Server nicht alle Seiten auf einmal abgerufen. Es wird die spezifischen Seiten lokalisieren und eine einzelne 8-KB-Seite nacheinander in den Speicher bringen. Lesen Sie die Daten daraus heraus und geben Sie das Ergebnis an. Dies wird nun fortgesetzt, wenn es sich um eine Situation handelt, in der weniger Speicher vorhanden ist. In diesem Fall werden alte Seiten gelöscht die Scheibe wie @Max wies darauf hin. Wie Sie richtig erraten haben, kann dieser geringe Speicher die Dinge verlangsamen, da einige Zeit für das Entfernen alter Seiten aufgewendet werden würde. Hier Checkpoint und Lazywriterkommt ins Bild. Lazywriter sorgt dafür, dass immer freier Speicher vorhanden ist, um neue Seiten auf die Festplatte zu bringen. Wenn ein niedriger freier Puffer angetroffen wird, wird dieser ausgelöst und es werden freie Speicherplätze für neue Seiten erstellt.
BEARBEITEN
Der Speicher für das Zusammenfügen und Filtern wird bereits vor der Ausführung der Abfrage festgelegt. Angenommen, es liegt tatsächlich eine Speicherverknappung vor, und der für die Ausführung des Vorgangs erforderliche Speicher ist nicht verfügbar. Der SQL Server-Prozessor gewährt "erforderlichen Speicher"
Zumindest wird die Abfrage ausgeführt, aber zur Laufzeit wird das Zwischenergebnis höchstwahrscheinlich an Tempdb übertragen, wodurch sie langsam wird. Ich empfehle dringend, dass Sie " Understanding Query Memory Grant" lesen
quelle