Die Details sind implementierungsabhängig, aber allgemein Sprich, Ergebnisse werden gepuffert. Das Ausführen einer Abfrage für eine Datenbank gibt eine Ergebnismenge zurück. Wenn es ausreichend klein ist, können alle Ergebnisse beim ersten Aufruf zurückgegeben werden, oder einige werden zurückgegeben, und es werden mehr Ergebnisse zurückgegeben, wenn Sie über das Ergebnisobjekt iterieren.
Stellen Sie sich die Sequenz folgendermaßen vor:
- Sie öffnen eine Verbindung zur Datenbank;
- Möglicherweise gibt es einen zweiten Aufruf, um eine Datenbank auszuwählen, oder es könnte als Teil von (1) erfolgen;
- Dieser Authentifizierungs- und Verbindungsschritt ist (mindestens) ein Roundtrip zum Server (wobei dauerhafte Verbindungen ignoriert werden);
- Sie führen eine Abfrage auf dem Client aus;
- Diese Anfrage wird an den Server gesendet;
- Der Server muss bestimmen, wie die Abfrage ausgeführt wird;
- Wenn der Server die Abfrage zuvor ausgeführt hat, befindet sich der Ausführungsplan möglicherweise noch im Abfrage-Cache. Wenn nicht, muss ein neuer Plan erstellt werden;
- Der Server führt die Anfrage wie angegeben aus und gibt ein Ergebnis an den Client zurück;
- Dieses Ergebnis enthält einige Zeilenpuffer, die von der Implementierung abhängig sind. Es können 100 Zeilen oder mehr oder weniger sein. Alle Spalten werden für jede Zeile zurückgegeben;
- Wenn Sie mehr Zeilen abrufen, wird der Client den Server nach weiteren Zeilen fragen. Dies kann der Fall sein, wenn der Client ausgeht, oder es kann präventiv erfolgen. Auch dies ist implementierungsabhängig.
Die Idee hinter all dem ist, Roundtrips zum Server zu minimieren, ohne zu viel zurückzusenden unnötige Daten, weshalb Sie nicht alle auf einmal zurückerhalten, wenn Sie eine Million Zeilen anfordern.
LIMIT-Klauseln – oder eigentlich jede Klausel – ändern die Ergebnismenge.
Schließlich ist (7) wichtig, weil SELECT * FROM table WHERE a = 'foo'
und SELECT * FROM table WHERE a = 'bar'
sind aus Sicht des Datenbankoptimierers zwei verschiedene Abfragen, sodass für jede separat ein Ausführungsplan festgelegt werden muss. Aber eine parametrisierte Abfrage (SELECT * FROM table WHERE a = :param
) mit unterschiedlichen Parametern ist eine Abfrage und muss nur einmal geplant werden (zumindest bis sie aus dem Abfragecache fällt).