PHP mysqli_use_result() — Ungepufferte Ergebnismengen erklärt
Erfahren Sie, wie mysqli_use_result() eine ungepufferte MySQL-Ergebnismenge initiiert, Unterschiede zu mysqli_store_result() und wann man es einsetzt.
Wenn Sie in PHP mit der mysqli-Erweiterung ein SELECT ausführen, muss MySQL die passenden Zeilen an Ihr Skript zurückgeben. Es gibt zwei Möglichkeiten, diese zu empfangen: gepuffert (die gesamte Ergebnismenge auf einmal in den PHP-Speicher kopieren) und ungepuffert (die Zeilen auf dem MySQL-Server belassen und sie einzeln abrufen). Die Funktion mysqli_use_result() initiiert den ungepufferten Modus.
Dieser Leitfaden erklärt, was mysqli_use_result() tut, wie es sich vom standardmäßigen gepufferten Modus unterscheidet, welche Regeln beim Einsatz zu beachten sind und wann es sich tatsächlich lohnt.
Was mysqli_use_result() tut
mysqli_use_result() initiiert den Abruf einer Ergebnismenge, die durch eine Abfrage erzeugt wurde, ohne die Zeilen in den PHP-Speicher zu kopieren. Anstatt alle Zeilen vorab herunterzuladen, behält der Server die Zeilen und Ihr Skript ruft sie einzeln beim Durchlaufen der Schleife ab.
Vergleichen Sie das mit dem Standardverhalten. Wenn Sie mysqli_query() aufrufen, ruft mysqli intern mysqli_store_result() für Sie auf — es lädt die gesamte Ergebnismenge in den Client-Speicher, bevor Ihr Code eine einzige Zeile sieht. Bei einer Abfrage, die zehn Millionen Zeilen zurückgibt, können das Hunderte von Megabytes PHP-Speicher sein. mysqli_use_result() vermeidet diese Kosten: Der Speicherverbrauch bleibt unabhängig von der Anzahl der zurückgegebenen Zeilen ungefähr konstant.
Syntax
mysqli_use_result(mysqli $mysql): mysqli_result|falseDie Funktion nimmt das Verbindungsobjekt (oder den Link) entgegen, das von mysqli_connect() zurückgegeben wird, und gibt bei Erfolg ein mysqli_result-Objekt zurück, oder false bei einem Fehler. Im objektorientierten Stil lautet die entsprechende Methode $mysqli->use_result().
Gepuffert vs. ungepuffert: Warum der Unterschied wichtig ist
Gepuffert (store_result) | Ungepuffert (use_result) | |
|---|---|---|
| Speicher auf PHP-Seite | Hält die gesamte Ergebnismenge | Ungefähr eine Zeile auf einmal |
mysqli_num_rows() | Sofort verfügbar | Erst nach dem Abrufen aller Zeilen |
mysqli_data_seek() | Unterstützt | Nicht unterstützt |
| Die Verbindung während des Lesens | Frei für neue Abfragen | Gesperrt bis zum Abschluss |
| Am besten geeignet für | Kleine/mittlere Ergebnismengen | Sehr große Ergebnismengen |
Der wesentliche Kompromiss: Der ungepufferte Modus ist speicherschonend, belegt aber die Verbindung. Sie können auf derselben Verbindung keine weitere Abfrage ausführen, bis Sie alle Zeilen abgerufen (oder das Ergebnis freigegeben) haben. Der gepufferte Modus ist das Gegenteil — speicherintensiver, aber die Verbindung ist frei, sobald die Abfrage zurückkehrt.
So verwenden Sie mysqli_use_result()
1. Verbindung zum MySQL-Server herstellen
Öffnen Sie zuerst eine Verbindung mit mysqli_connect():
<?php
$host = 'localhost';
$user = 'username';
$password = 'password';
$database = 'mydatabase';
$connection = mysqli_connect($host, $user, $password, $database);
if (!$connection) {
die('Connection failed: ' . mysqli_connect_error());
}2. Abfrage ausführen und ungepuffertes Abrufen starten
Für den ungepufferten Modus müssen Sie die Abfrage ausführen, ohne mysqli aufzufordern, das Ergebnis zu speichern. Verwenden Sie das Flag MYSQLI_USE_RESULT mit mysqli_query() (oder rufen Sie mysqli_real_query() auf), und rufen Sie dann mysqli_use_result() auf:
$sql = "SELECT id, name FROM users";
// MYSQLI_USE_RESULT tells mysqli NOT to buffer the rows.
mysqli_real_query($connection, $sql);
$result = mysqli_use_result($connection);
if ($result) {
while ($row = mysqli_fetch_assoc($result)) {
// Process one row at a time — only this row lives in PHP memory.
print_r($row);
}
mysqli_free_result($result);
}Jeder Aufruf von mysqli_fetch_assoc() holt die nächste Zeile direkt aus der Leitung. Sie können auf dieselbe Weise auch mysqli_fetch_row(), mysqli_fetch_array() oder mysqli_fetch_all() verwenden.
3. Ergebnis immer freigeben
Der Aufruf von mysqli_free_result() ist hier wichtiger als im gepufferten Modus: Bis das Ergebnis freigegeben (oder vollständig gelesen) ist, bleibt die Verbindung gesperrt und für andere Abfragen nicht verwendbar.
Regeln und Fallstricke
- Alle Zeilen vor der nächsten Abfrage lesen. Solange ein ungepuffertes Ergebnis offen ist, ist die Verbindung beschäftigt. Der Versuch, eine weitere Abfrage auszuführen, bevor die Schleife abgeschlossen ist, löst einen „Commands out of sync"-Fehler aus. Schließen Sie die Schleife ab oder rufen Sie zuerst
mysqli_free_result()auf. - Keine Zeilenanzahl im Voraus.
mysqli_num_rows()gibt die korrekte Anzahl erst zurück, nachdem Sie alle Zeilen abgerufen haben, da der Server dem Client noch nicht mitgeteilt hat, wie viele es sind. - Kein wahlfreier Zugriff.
mysqli_data_seek()funktioniert nicht bei ungepufferten Ergebnissen — Sie können sich nur vorwärts bewegen. - Ein Ergebnis pro Verbindung. Sie können auf einer Verbindung jeweils nur ein ungepuffertes Ergebnis offen halten.
Wann sollte man es verwenden?
Greifen Sie auf mysqli_use_result() zurück, wenn eine Abfrage weit mehr Daten zurückgibt, als Sie im Speicher halten möchten — z. B. beim Exportieren einer großen Tabelle als CSV, beim Streamen eines Berichts oder beim zeilenweisen Einspeisung eines langen Ergebnisses in einen anderen Prozess. In diesen Fällen ist der konstante Speicherverbrauch ein echter Vorteil.
Für alltägliche Abfragen, die eine Handvoll oder auch einige Tausend Zeilen zurückgeben, bleiben Sie beim standardmäßigen gepufferten Modus über mysqli_query(). Der Komfort von mysqli_num_rows(), wahlfreiem Zugriff und einer freien Verbindung überwiegt fast immer die bescheidene Speicherersparnis.
Fazit
mysqli_use_result() startet eine ungepufferte MySQL-Ergebnismenge und ruft Zeilen einzeln ab, sodass der Speicherverbrauch auch bei riesigen Ergebnismengen niedrig bleibt. Der Preis dafür ist, dass die Verbindung gesperrt ist, bis Sie das Lesen abgeschlossen haben, mysqli_num_rows() und mysqli_data_seek() nicht verfügbar sind und das Ergebnis umgehend freigegeben werden muss. Verwenden Sie es für wirklich große Datensätze; bevorzugen Sie den gepufferten Standard für gewöhnliche Abfragen.