Hi Mathias,
Einfache Frage: Wieso? Auf dem ersten Blick erscheint es logisch,
aber auf den zweiten Blick merkt man, dass das komplette MySQL-
Resultat schon im Speicher vorhanden ist, denn die Abfrage ist schon
längst abgeschlossen, wenn die Arrays daraus "gefetcht" werden.
Ich kenne die PHP-Interna nicht, aber ich nehme an, dass die MySQL-
Daten erst zeilenweise in von PHP (bzw. C) bearbeitbare Daten
umgewandelt werden (der Vorgang des Fetchens :)).
Nämlich wenn schon direkt nach der MySQL-Query die kompletten
Ergebnisdaten in ein für PHP verarbeitbares Format umgewandelt
werden, wäre das zeilenweise Auslesen eine Farce, da die Daten Zeile
für Zeile im Speicher verdoppelt würden, wenn man sie in eine
Variable/einen Array schreibt. Denn intern würde ein Art
verschachtelter Array bereits existieren.
hm. Ich weiß es genauso wenig wie Du, aber man kann ja mal ein bißchen
philosophieren.
Wenn die "PHP-Maschine" ein hinreichend enges Interface zum Memory-Pool
von mySQL hätte, dann könnte ein Fetch natürlich in der tat daraus be-
stehen, einen Pointer auf eine dort bereits existierende Datenstruktur
durchzureichen. In diesem Falle würden die Daten nie zweimal im Speicher
stehen. Allerdings wäre das nicht wirklich die maschinenunabhängigste
aller Implementierungen.
Insofern rechne ich doch eher damit, daß PHP beim "fetch" brav eine Kopie
anlegt. Und _dann_ möchte ich eben nicht das gesamte Ergebnis der Query
_zweimal_ im Arbeitsspeicher stehen haben - einmal im mySQL-Pool, wo es
erst nach dem Ende der Schleife freigegeben werden kann, und noch einmal
im Adreßraum des PHP-Prozesses, der dort seinen assoziativen Array in den
Speicher prügelt. Mit etwas Pech swappen die beiden dann auch noch fröh-
lich gegeneinander ...
Wie sehen denn die MySQL-Ergebnisdaten aus, gibt es dort überhaupt so
etwas wie eine Datensatztrennung, welche es ermöglicht, einen Teil des
Results zu lesen, ohne dass gleich das komplette Result
geparst/umgewandelt werden muss?
Also eine Struktur werden die elementaren Datensätze sicherlich haben.
Welche genau, das hängt sicherlich vom jeweiligen Tabellentreiber ab -
da ist die Angabe "mySQL" wohl nicht genau genug.
Ich bearbeite MySQL-Ergebnisse zwar auch immer zeilenweise und sehe
auch ein, dass es klug sein mag, aber ob es wirklich notwendig (weil
ökonomisch) ist, ist bei einer nicht speichernahen Sprache wie PHP
nicht einfach erkennbar.
Wenn man sich so etwas einmal angewöhnt hat, dann macht man es automa-
tisch richtig, wenn man an eine Sprache gerät, bei der es wichtig ist.
Das ist einfacher, als von jedem neuen Interpreter den Quelltext zu
lesen. ;-)
Der Trick ist, den Bruch zwischen den beiden Universen zu verstehen.
SQL denkt in Mengen; PHP etc. denken in Listen, Schleifen, endlichen
Variablen. Also läßt sich eine Menge von Zeilen nicht durch eine ein
fache Zuweisung aus der Datenbank ziehen,
Doch, eben das passiert: eine MySQL-Abfrage liefert *alle* Datensätze
(dürfte in Perl nicht anders sein?). Danach hat PHP die gesamten
Ergebnisdaten im Speicher und man kann sie aber nur zeilenweise
"abrufen"...
Gerade _weil_ man sie dann aber nur zeilenweise abrufen kann, macht es
gar keinen Sinn, sie gleichzeitig im Speicher zu halten. Es sei denn,
man muß eine Operation auf ihnen durchführen, für die man alle auf ein-
mal braucht - Sortieren, um ein Beispiel zu nennen.
(Dann hätte man allerdings im vorliegenden Szenario, bei dem man genau
dies besser der Datenbank überlassen sollte, etwas verkehrt gemacht.)
Noch bevor das Result durch mysql_(result|fetch_*) bearbeitet wird,
kann man die Verbindung zur Datenbank schließen, die Datenbank wird
also nur einmal befragt, nicht zeilenweise.
sondern nur durch eine Schleife über die gefundenen Zeilen
Wie oft die Datenbank tatsächlich befragt wird, das muß man der Hoch-
sprache ja gar nicht ansehen. Wenn ich in Pascal ein Zeichen lese, dann
greif das Laufzeitsystem dafür ja auch nicht auf die Festplatte zu,
sondern erst mal auf seinen I/O-Buffer, und erst wenn der ausgelutscht
ist, wird er neu geladen. Zwischen diesen Abstraktionsebenen eine
Schicht zu ziehen, welche die Sache performanter macht, das ist eine
der Leistungen von Laufzeitsystemen - analog dazu, daß Perl und PHP dem
Anwender ersparen, über das Allozieren von Arbeitsspeicher zu sehr im
Detail nachdenken zu müssen. (Aber einen Hash mit einer Milliarde Ein-
träge aufzubauen ist auch in Perl noch keine gute Idee. ;-)
"Wieso?" Wieso gibt eine keine Funktion, die ein komplettes Result
(alle gefundenen Datensätze) in einen Array "überführt"? Wenn man
arraytypische Operationen durchführen will, ist es sinnlos, die
Datensätze einzeln in einen Array einzusortieren, denn der vom Result
belegte Speicher kann erst über mysql_free_result freigegeben werden,
wenn bereits ein Duplikat des kompletten Arrays im Speicher vorhanden
ist. Man müsste also vermeiden, dass dies überhaupt passieren kann...
Eben - es reicht ja, wenn das "fetch" eine Zeile abgreift. Warum soll ich
die noch mal in einem lokalen Array speichern und dann auf den zugreifen?
Wenn man bedenkt dass man mit mysql_data_seek() immerhin innerhalb des
Results herumspringen kann, also würde man einen Zeiger innerhalb eines
Arrays setzen, dann muss das Result definitiv schon *vor* jeglichem
fetch_*-Aufruf in einer arrayförmigen Speicherstruktur vorhanden
sein... *mutmaß*
Das denke ich auch.
*g* Schon lustig, wenn man keine Ahnung hat, aber Theorien aufstellt.
So etwas nennt man "Wissenschaft" - etwas tun, das Wissen schafft. ;-)
Viele Grüße
Michael
P.S.: http://www.laum.uni-hannover.de/ilr/lehre/VerwWiss/Ptm_WissTheo.htm#theorie