Shared Memory / Semaphoren - Verständnisproblem
Markus Stolpe M-T-S[AT]GMX.NET
- programmiertechnik
hallo,
ich hoffe, mir kann jemand bei nachfolgendem problem:
angenommen, ich hab eine datenbank...sagen wir telefonbuch. es gibt da verschiedene namen, zu jedem namen noch telefonnummer usw.
insgesamt 2 millionen. die zahl ist nicht fest, sondern steigend.
abfragen will ich mit semaphoren ermöglichen. hierzu verwende ich PHP 4.0, 4 GB RAM,...
da ja shared memory segmente bzw. semaphoren (hab den unterschied nicht ganz verstanden) bestimmte grössenrestriktionen haben, die man nicht ganz nach belieben ändern kann, will ich nun also die ganzen einträge alphabetisch unterteilen.
dies kann ich jeweils nach dem anfangsbuchstaben oder nach den ersten beiden anfangsbuchstaben machen.
nach meinen laienhaften berechnungen benötige ich so je buchstabe derzeit 20 bis 110 MB (s gibt's öfter als z.b. q).
da ja die ersten dinger (shared memory segmente?) an MB-Zahlen zwischen 1 - 128 MB bei Linux gebunden sind, verwende ich demnach 24 segmente + 10 segmente für zahlen.
das ganze über PHP mittels: shm_attach()
so ein segment scheint aus semaphoren zu bestehen, die ich mittels
sem_get() bzw. shm_get_var() aufrufe. hierbei verwende ich auch einen Key, den ich durch den (oder: die beiden) anfangsbuchstaben generiert habe. ...das, was ich dort heraushole, ist ein $array, in dem wiederum den eigentlichen werte herauslese.
das ganze funktionierte auch, bis ich dann auf irgendwelche restriktionen seitens der standardinstallation von linux/apache gestossen bin. ich wollte dann verschiedene werte ändern, um es zu ermöglichen, dabei fiel mir allerdings auf, dass ich gar nicht weiss, ob ich nun semaphore, segment oder sonstwas erweitern soll bzw. wo ich meine "ach-so-tolle" alphabetische unterteilung nun wirklich anbringen soll und wo ich meine arrays mit den ganzen werten reinschreiben soll.
zur veranschaulichung hier so ein kleiner aufbau (wie gesagt, ich weiss nun nicht, was "höher" steht: semaphore (shm_get) oder shared memory segment (shm_attach).
SEGMENTE: gesamt 24 fürs alphabet + 10 für zahlen
--> SEMAPHOREN: Keys hierfür ebenso generiert aus den anfangsbuchstaben/zahlen
---> in die semaphoren greif ich dann rein und hol mir mittels des ermittelten sem_varkeys (selbe wie keys) für semaphoren das entsprechende array raus, aus dem ich dann den wert lese.
WIE UNTERTEILE ICH DAS GANZE ALSO AM BESTEN?
kann übrigens sein, dass ich gänzlich einen grundlegenden fehler beim aufbau begangen habe....
für jedwede hilfe bin ich äusserst dankbar! ebenso für tipps, verweise etc.!
besten dank!!
Markus Stolpe
Sup!
Dein Unternehmen hört sich komplett wahnsinnig an.
Du willst eine Datenbank komplett im RAM halten, und anscheinend... selbst programmieren? Was soll das bringen?
Und Semaphoren dienen einzig und allein dazu, gegenseitigen Ausschluss von "Zugreifern" zu realisieren. Auf das Shared Memory kann eigentlich jeder immer zugreifen. Wenn sich allerdings alle Teilnehmer "richtig" verhalten und brav Semaphoren anfordern, kann man ein totales Chaos, was entsteht, wenn alle durcheinander schreiben, verhindern.
Ehm... aber warum ist denn eine normale DB eigentlich nicht gut genug?
Gruesse,
Bio
Hallo Bio,
Dein Unternehmen hört sich komplett wahnsinnig an.
Full ACK
Auf das Shared Memory kann eigentlich jeder immer zugreifen.
Ney, ney, ney, das stimmt so nicht. Nur autorisierte Prozesse duerfen auf shm-Segmente
zugreifen... wo kaemen wir hin, wenn alle moeglichen Programme auf den Speicher zugreifen
duerften? Sind wir hier unter Windows?! *scnr* ;))
Gruesse,
CK
Sup!
Ney, ney, ney, das stimmt so nicht. Nur autorisierte Prozesse duerfen auf shm-Segmente
zugreifen... wo kaemen wir hin, wenn alle moeglichen Programme auf den Speicher zugreifen
duerften? Sind wir hier unter Windows?! *scnr* ;))
Ich meinte eher so "jeder" im Sinne von "jeder Teilnehmer", also jedes von den Programmen, die er da so laufen lassen wollte.
Aber latuernlich hast Du Recht ;-)
Gruesse,
Bio
Hi Ritter,
Ehm... aber warum ist denn eine normale DB eigentlich
nicht gut genug?
das "supporte" ich mal:
http://www.mysql.com/doc/en/HEAP.html
Viele Grüße
Michael
Hallo,
angenommen, ich hab eine datenbank...sagen wir telefonbuch. es gibt da verschiedene
namen, zu jedem namen noch telefonnummer usw.
insgesamt 2 millionen. die zahl ist nicht fest, sondern steigend.
Mir ist nicht klar, warum du hier shared memory verwenden willst.
abfragen will ich mit semaphoren ermöglichen.
Semaphoren koennen keine Abfragen ermoeglichen :) Semaphoren synchronisieren nur Zugriffe.
da ja shared memory segmente bzw. semaphoren (hab den unterschied nicht ganz verstanden)
Shared Memory ist Speicher, der gemeinsam genutzt werden kann. Semaphoren sind Mechanismen
(etwa Speicher-Blockaden oder spezielle Dateien), die den Zugriff auf Ressourcen
synchronisieren. Beispiel: du hast zwei Programme, die schreibend und lesend auf dieselbe
Datei zugreifen. Lesen duerfen mehrere Programme gleichzeitig, aber schreiben sollte immer
nur ein Programm. Ueblicherweise wird das ueber flock() geloest; wie flock() jedoch
implementiert ist, ist natuerlich frei. Eine Moeglichkeit hierzu waere es, einen Semaphor
zu locken. Ist der Semaphor gelockt, so wird das Programm, das den Lock anfordert, solange
in den Sleep-Modus geschickt, bis es an der Reihe ist und den ungelockten Semaphor kriegt.
Den lockt es dann, um seinerseits den exklusiven Zugriff zu garantieren.
da ja die ersten dinger (shared memory segmente?) an MB-Zahlen zwischen 1 - 128 MB bei
Linux gebunden sind, verwende ich demnach 24 segmente + 10 segmente für zahlen.
Du meinst sicher 26 Buchstaben (das Alphabet hat 26 Zeichen) + Sonderzeichen + Zahlen. Was
wuerdest du sonst mit einem Namen wie Ímir machen? :)
so ein segment scheint aus semaphoren zu bestehen, die ich mittels
sem_get() bzw. shm_get_var() aufrufe.
Nein. Du beziehst dich sicher auf das Beispiel im Manual; da wird ein Semaphor benutzt, um
den exklusiven Zugriff zu garantieren. Aber man *muss* keinen Semaphor benutzen. Und
shm_get_var() ist etwas komplett anderes als sem_get() -- mit dem einen holst du dir eine
Variable aus dem Shared-Memory-Bereich, mit dem anderen host du dir ein Semaphor.
das ganze funktionierte auch, bis ich dann auf irgendwelche restriktionen seitens der
standardinstallation von linux/apache gestossen bin. ich wollte dann verschiedene werte
ändern, um es zu ermöglichen, dabei fiel mir allerdings auf, dass ich gar nicht weiss, ob
ich nun semaphore, segment oder sonstwas erweitern soll
Das kommt auf die Fehlermeldung an. Semaphoren, wenn du nicht genuegend Semaphoren bekommst,
Shared-Memory, wenn du nicht genuegend Shared-Memory alloziieren kannst :) Eine
funktionierende Glaskugel habe ich leider nicht.
bzw. wo ich meine "ach-so-tolle"
alphabetische unterteilung nun wirklich anbringen soll und wo ich meine arrays mit den
ganzen werten reinschreiben soll.
Die Arrays legst du in das Shared-Memory-Segment.
SEGMENTE: gesamt 24 fürs alphabet + 10 für zahlen
26, und Sonderzeichen hast du noch immer nicht drin :)
WIE UNTERTEILE ICH DAS GANZE ALSO AM BESTEN?
Warum willst du hier shared memory benutzen? Shared memory ist fuer geringe Datenmengen, auf
die extrem schnell zugegriffen werden muss. Dazu gehoert ganz sicher *keine* Adress-DB mit
insgesamt 2 Mio Eintraegen.
kann übrigens sein, dass ich gänzlich einen grundlegenden fehler beim aufbau begangen
habe....
IMHO ja. Warum benutzt du nicht ein ganz normales DBS?
Gruesse,
CK
hallo!
vielen herzlichen dank für die antworten! ich hätte ja gar nicht gedacht, dass sich doch so zahlreiche mit sowas auskennen :)
ich erlaube mir, noch ein paar anschlussfragen zu stellen:
Mir ist nicht klar, warum du hier shared memory verwenden willst.
mysql scheint nun deutlich an die grenzen gestossen zu sein. in stosszeiten sind evtl. auch selects von 255/s möglich. jedenfalls knapp. mysql lockte sich anfänglich öfter mal ("in benutzung" lt. phpmyadmin -> bug mit mysql patch beseitigt, mittlerweile scheint apache nicht mehr mit mysql kommunizieren zu können. problem kann nicht eingegrenzt werden, aber irgendwann hat mysql wohl auch seine grenzen....)
..., mit dem anderen host du dir ein Semaphor.
ah! okay, ich dachte semaphoren seien nochmal irgend eine komische unterteilung...
e.c. sage ich imt sem_get($shm_id,1)) lediglich, dass "er" so 'ne semaphore kriegt, die eben nur für einen benutzt werden kann?
» Das kommt auf die Fehlermeldung an. Semaphoren, wenn du nicht genuegend Semaphoren bekommst,
Shared-Memory, wenn du nicht genuegend Shared-Memory alloziieren kannst :)
mittlerweile bekomme ich leider nur noch "die seite kann nicht angezeigt werden." die fehlermeldung war was mit sinngemäss "nicht genügend space left. der RAM war jedoch noch ausreichend, gehe ich davon aus, dass der in der php.ini definierte wert für jedes einzelne shared memory segment gilt, wovon ich ausging.
lt. google-recherche bin ich dann auf postgreSQL-infos gestossen. dort ist die fehlermeldung hinlänglich bekannt und als lösung solle man SHMMAX hochsetzen. hab dann auch diverses probiert, was wohl nicht funktioniert hat und fand dann durch ipcs -u und -l leider dann so viele angaben, dass ich feststellen musste, dass dies mein einfühlungsvermögen in sowas übersteigt.
schlussendlich hatte ich dann auch bedenken, dass ich dennoch für verschiedenes einen wert evtl. nicht hoch genug setze bzw. zu hoch, so dass evtl. meine SHM-dinger noch irgendwie apache beeinträchtigen.
Warum willst du hier shared memory benutzen?
wie gesagt: jede datenbank scheint mit der unmenge an selects probleme zu bekommen. alternativ - da auch mittlerweile einfacher zu realisieren - zog ich ein filesystem in betracht; files mit den entsprechenden einträgen werden dann eben includiert - falls vorhanden - und - falls nicht vorhanden - aus der DB ausgelesen, dann das file geschrieben.
persönlich hatte ich dann mehr zu SHM vertrauen. der server hat 4 GB Ram intus.
wieder viel geschrieben, meine fragen kurz zusammengesfasst:
besten dank nochmals!
Markus Stolpe
Hallo,
Mir ist nicht klar, warum du hier shared memory verwenden willst.
mysql scheint nun deutlich an die grenzen gestossen zu sein. in stosszeiten sind evtl.
auch selects von 255/s möglich. jedenfalls knapp. mysql lockte sich anfänglich öfter mal
("in benutzung" lt. phpmyadmin -> bug mit mysql patch beseitigt, mittlerweile scheint
apache nicht mehr mit mysql kommunizieren zu können. problem kann nicht eingegrenzt
werden, aber irgendwann hat mysql wohl auch seine grenzen....)
Dann benutze ein anderes DBS :) DB2 kommt IMHO dicke mit sowas klar.
e.c. sage ich imt sem_get($shm_id,1)) lediglich, dass "er" so 'ne semaphore kriegt, die
eben nur für einen benutzt werden kann?
Solange du dieselbe ID benutzt, ja.
Warum willst du hier shared memory benutzen?
wie gesagt: jede datenbank scheint mit der unmenge an selects probleme zu bekommen.
alternativ - da auch mittlerweile einfacher zu realisieren - zog ich ein filesystem in
betracht; files mit den entsprechenden einträgen werden dann eben includiert - falls
vorhanden - und - falls nicht vorhanden - aus der DB ausgelesen, dann das file
geschrieben.
Ich glaube nicht, dass das wirklich was bringt.
- welche werte müsste ich nun definitiv im apache-kernel erhöhen, die sich auf die
anzahl der reinzulegenden werte (arrays) von derzeit 2 Mio beziehen? gibts hier irgendwo
verständliche informationen wie das zu handeln ist
Apache-Kernel? Den gibts nicht. Du meinst den Linux-Kernel. Und da wirst du wohl woanders
fragen muessen, mir ist die Konstante fuer Semaphoren leider nicht bekannt.
- ist in meinem fall von dem SHM evtl. komplett abzuraten und vielleicht doch ein
"file-cache-system" zu verwenden?
Ich wuerde ein DBS benutzen. Denk dir halt ein anderes Datenmodell aus und benutz ein
richtiges DBS (DB2, Oracle).
Gruesse,
CK
Moin!
mysql scheint nun deutlich an die grenzen gestossen zu sein. in stosszeiten sind evtl. auch selects von 255/s möglich. jedenfalls knapp. mysql lockte sich anfänglich öfter mal ("in benutzung" lt. phpmyadmin -> bug mit mysql patch beseitigt, mittlerweile scheint apache nicht mehr mit mysql kommunizieren zu können. problem kann nicht eingegrenzt werden, aber irgendwann hat mysql wohl auch seine grenzen....)
Ich weiß ja nicht, was du mit MySQL angestellt hast, aber üblicherweise kommt es mit SELECTs auch in großen Datenmengen am besten klar. 2 Millionen Einträge sind doch nicht wirklich viel.
Wenn deine SELECTs zu lange dauern, könnte das an einem fehlenden, für diese SELECTs passenden Index liegen. Da kann man extrem viel Performance rausholen.
Gegen irgendwelche MySQL-Bugs hilft natürlich ein Update - da du nichts dazu gesagt hast, welche Versionen du hast, kanns auch keine Empfehlung geben, was man dagegen tun kann.
Da du die Frage ursprünglich gestellt hast: Ja, dein Ansatz, alle Daten im Speicher zu halten, ist ziemlich gewagt. Es gibt reichlich Datenbanksysteme auf diesem Planeten, von billig und schnell über kostenpflichtig und für die Aufgabe unzureichend bis hin zu extrem teuer, schnell, sehr mächtig und wahrscheinlich überdimensioniert.
Wenn PHPMyAdmin bzw. Apache mit MySQL keine Verbindung mehr kriegt, dann wird irgendwas kaputtgegangen sein oder sich geändert haben. Bevor ich mir jedenfalls einen komplett neuen Ansatz ausdenke, ohne wirklich Ahnung davon zu haben (deine Verwirrungen um Shared Memory und Semaphoren deuten es an), würde ich mir erstmal überlegen, wie das alte System zu besserer Leistung zu überreden ist.
wieder viel geschrieben, meine fragen kurz zusammengesfasst:
- welche werte müsste ich nun definitiv im apache-kernel erhöhen, die sich auf die anzahl der reinzulegenden werte (arrays) von derzeit 2 Mio beziehen? gibts hier irgendwo verständliche informationen wie das zu handeln ist
Überleg doch mal selbst: 2 Millionen Datensätzt - wie groß ist einer durchschnittlich? Da davon auszugehen ist, dass die Datensätze mindestens mit einem Pointer im Speicher abgelegt werden, und dieser Pointer auf 32-Bit-Plattformen aus 4 Byte bestehen, belegst du _mindestens_ schon mal 8 Megabyte Speicher nur, um ein Minimum an Verwaltungsinformationen abzulegen. Dazu kommt, dass ein Datensatz (du sprachst von "Telefonliste) wohl eher aus 100 Byte denn aus 10 besteht - was prompt einen Speicherbedarf von mindestens nochmal 200 Megabyte nach sich zieht für die reinen Daten (nach einer sehr konservativen Schätzung). Da davon auszugehen ist, dass die Sache mit nur einem Pointer nicht getan ist, bzw. du auf die Art der Speicherverwaltung in PHP nicht genauestens Einfluss nehmen kannst, dürfte der tatsächliche Wert weit darüber liegen. Mit anderen Worten: Du belegst mindestens 256 MB, eher noch 512 MB oder gar 1 GB (je nachdem, ob du nun 100 Byte, 200 Byte oder 400 Byte pro Datensatz verwaltest) an RAM-Speicher nur für die Daten. Hinzu kommt dann noch ein vernünftiger Index, denn obwohl RAM-Zugriffe sehr schnell sind: Irgendwie will man doch eher selten die gesamte Liste linear auslesen.
Wenn es aber um die Performance geht, muss der Server viel RAM haben. Leider ist die Obergrenze für RAM bei derzeitigen Systemen bei 4 GB. Das bedeutet, dass du mindestens ein Viertel des RAM-Speichers mit deinen Daten belegst. Das erscheint mir nicht sehr vorteilhaft. Und es legt die Obergrenze der Datenmenge pro Datensatz auf 2 Kilobyte - dann wären deine 4 GB mit 2 Millionen Datensätzen vollkommen ausgelastet. Ich weiß nicht, wie es mit RAM-Swapping aussieht, aber das ist ganz sicher eine Performancebremse, insbesondere, wenn die falschen RAM-Bereiche ausgelagert wurden.
- ist in meinem fall von dem SHM evtl. komplett abzuraten und vielleicht doch ein "file-cache-system" zu verwenden?
Es wäre sinnvollerweise eine funktionierende Datenbank zu verwenden... :)
- Sven Rautenberg
Hallo Sven,
Ich weiß ja nicht, was du mit MySQL angestellt hast, aber üblicherweise kommt es mit
SELECTs auch in großen Datenmengen am besten klar. 2 Millionen Einträge sind doch nicht
wirklich viel.
Richtig. Aber ich glaube, es liegt hier weniger an der Datenmenge sondern viel mehr an der
Anzahl der Queries. Und da hat MySQL ganz arge Probleme... wenn die so 10/s uebersteigt,
wird das Ding ziemlich ueberlastet (kommt natuerlich ganz auf das System an).
Wenn deine SELECTs zu lange dauern, könnte das an einem fehlenden, für diese SELECTs
passenden Index liegen. Da kann man extrem viel Performance rausholen.
EXPLAIN koennte hier sehr behilflich sein.
Überleg doch mal selbst: 2 Millionen Datensätzt - wie groß ist einer durchschnittlich? Da
davon auszugehen ist, dass die Datensätze mindestens mit einem Pointer im Speicher
abgelegt werden, und dieser Pointer auf 32-Bit-Plattformen aus 4 Byte bestehen, belegst
du _mindestens_ schon mal 8 Megabyte Speicher nur, um ein Minimum an
Verwaltungsinformationen abzulegen.
Du vergisst, dass es hier um PHP geht. PHP benutzt ein wenig mehr Speicher fuer seine
Datenstrukturen. Ich bin ehrlich gesagt sogar ueberrascht, das eine deep copy von den Arrays
gemacht wird... da scheint Sascha Schumann viel Arbeit investiert zu haben.
Wenn es aber um die Performance geht, muss der Server viel RAM haben. Leider ist die
Obergrenze für RAM bei derzeitigen Systemen bei 4 GB.
Nur bei x86-Systemen. Die ist naemlich relativ rueckstaendig, es gibt seit Jahren schon
64Bit-Plattformen.
Das bedeutet, dass du mindestens ein Viertel des RAM-Speichers mit deinen Daten belegst.
Das erscheint mir nicht sehr vorteilhaft. Und es legt die Obergrenze der Datenmenge pro
Datensatz auf 2 Kilobyte - dann wären deine 4 GB mit 2 Millionen Datensätzen vollkommen
ausgelastet. Ich weiß nicht, wie es mit RAM-Swapping aussieht, aber das ist ganz sicher
eine Performancebremse, insbesondere, wenn die falschen RAM-Bereiche ausgelagert wurden.
Vor allem kann mit dem System dann nicht mehr richtig gearbeitet werden. Speicher kann nur
in Bloecken reserviert werden. Wenn man also einen sehr grossen Block reserviert, muss uU
der komplette Speicher umstrukturiert werden, damit soetwas moeglich ist. Wer Lust hat, kann
ja mal folgendes kleines C-Programm ausprobieren (das reserviert 4, 16, 32, 64, 128, 256MB
RAM und gibt sie dann wieder frei):
#include <stdio.h>
#include <stdlib.h>
int main(void) {
long size;
char *ptr = NULL;
for(size=4;size<512;size*=2) {
printf("trying to allocate %ld mb\n",size*1024L*1024L);
ptr = realloc(ptr,size*1024L*1024L);
if(!ptr) {
fprintf(stderr,"error: could not reallocate to %ld\n",size*1024L*1024L);
return EXIT_FAILURE;
}
}
free(ptr);
printf("allocated successfully :)\n");
return EXIT_SUCCESS;
}
Leute mit nennenswert mehr als 256MB RAM koennen natuerlich dementsprechend die Grenzen
anpassen.
Gruesse,
CK
Hallo, Christian,
nicht dass ich sonderlich Ahnung hätte, aber ich lese interessiert mit... eine Frage habe ich:
Überleg doch mal selbst: 2 Millionen Datensätzt - wie groß ist einer durchschnittlich? Da
davon auszugehen ist, dass die Datensätze mindestens mit einem Pointer im Speicher
abgelegt werden, und dieser Pointer auf 32-Bit-Plattformen aus 4 Byte bestehen, belegst
du _mindestens_ schon mal 8 Megabyte Speicher nur, um ein Minimum an
Verwaltungsinformationen abzulegen.
Du vergisst, dass es hier um PHP geht. PHP benutzt ein wenig mehr Speicher fuer seine
Datenstrukturen. Ich bin ehrlich gesagt sogar ueberrascht, das eine deep copy von den Arrays
gemacht wird... da scheint Sascha Schumann viel Arbeit investiert zu haben.
Was ist mit "deep copy der Arrays" gemeint?
Ich diskutierte kürzlich mit Michael darüber, wie PHP mit einem MySQL-Result umgeht und ob die mysql_fetch_*-Funktionen die Daten womöglich im Speicher verdoppeln. Ein Lesen bzw. Umwandeln des Ergebnisses in einen PHP-Array Zeile für Zeile bzw. Datensatz für Datensatz wäre sinnlos, wenn das Ergebnis schon vorher in einer Array-Speicherstruktur vorhanden wäre, ein $datensatz_array=mysql_fetch_*(...) wäre demnach ein Verdoppeln der Daten im Speicher, was äußerst speicherintensiv wäre, wenn man Operationen mit allen Datensätzen des Resultates vorhat (welche nicht von der Datenbank ausgeführt werden können). Wir wussten beide nicht, ob diese Annahme stimmen mag, vielleicht weißt du etwas dazu und meintest genau das mit deep copy....
(Der Thread ist momentan nicht auffindbar, da der Server überlastet ist.)
Grüße,
Mathias
Hallo,
Was ist mit "deep copy der Arrays" gemeint?
Naja, in C sind Array Pointer auf Speicherbloecke. Jetzt kann man den Array auf zwei Arten
kopieren: 'deep' und 'shallow'. 'Shallow' hiesse, man kopiert nur den Pointer auf den
Speicherbereich, man hat also zweimal denselben Speicherbereich und damit faktisch denselben
Array. 'Deep' hiesse, man dupliziert den Speicherbereich. Es koennte natuerlich sein, dass
die Array-Elemente wieder nur Pointer sind, bei einer deep copy muessten dann die
Datenstrukturen, auf die die Array-Elemente zeigen, auch verdoppelt werden.
Ich diskutierte kürzlich mit Michael darüber, wie PHP mit einem MySQL-Result umgeht und ob
die mysql_fetch_*-Funktionen die Daten womöglich im Speicher verdoppeln.
Natuerlich tun sie das ;)
Ein Lesen bzw. Umwandeln des Ergebnisses in einen PHP-Array Zeile für Zeile bzw. Datensatz
für Datensatz wäre sinnlos, wenn das Ergebnis schon vorher in einer Array-Speicherstruktur
vorhanden wäre,
Ist es aber nicht. Es ist nur in einem mysql_result vorhanden, als Referenz auf einen
Speicherbereich. In dem Speicherbereich stehen die unaufbereiteten, von MySQL serialisierten
Ergebnisse. Bei jedem mysql_fetch_irgendwas wird der Pointer in der mysql_result-Struktur um
einen Datensatz weiter nach vorn gesetzt.
ein $datensatz_array=mysql_fetch_*(...) wäre demnach ein Verdoppeln der Daten im Speicher,
was äußerst speicherintensiv wäre, wenn man Operationen mit allen Datensätzen des
Resultates vorhat (welche nicht von der Datenbank ausgeführt werden können).
Oh, es ist aber notwendig. Irgendwie muss man die Daten ja durch den Socket kriegen. Dazu
muessen die 'serialisiert', in Textform gebracht werden. Wie genau das Format aussieht,
ist sicher dokumentiert, bei Bedarf bei mysql.com nachlesen :) Und auf der Client-Seite wird
das ganze ueber die mysql_fetch_irgendwas-Funktionen wieder umgewandelt in eine andere Form,
in diesem Fall 'mysql_row's. Diese mysql_row wird wieder umgewandelt in einen PHP-Array,
damit die Daten auch in PHP erreichbar sind.
Gruesse,
CK
Hi Markus,
vielen herzlichen dank für die antworten! ich hätte
ja gar nicht gedacht, dass sich doch so zahlreiche
mit sowas auskennen :)
Deine Thematik ist interessant und fordert die Antwortenden - das macht Spaß. :-)
mysql scheint nun deutlich an die grenzen gestossen
zu sein. in stosszeiten sind evtl. auch selects von
255/s möglich. jedenfalls knapp.
Hm. Sind das 255 client-Requests pro Sekunde (das würde mich von den Socken hauen), oder macht ein Client ganz viele SELECTs?
Ich würde mal hinterfragen, ob Du die Zahl der SELECTs nicht dramatisch reduzieren kannst. Leider müßtest Du dafür ins Detail gehen - aber es riecht mir danach, Deinen Entwurf daraufhin zu überprüfen, ob Du nicht eine oder mehrere Größenordnungen von SELECTs durch eine geänderte Architektur ersetzen kannst.
Beispiel: Wenn Du einen JOIN durch eine Schleife mit SELECTs über die zweite Tabelle simulierst, arbeitest Du massiv am Konzept der Datenbank vorbei, die genau das viel besser könnte. Einen so krassen Patzer möchte ich Dir natürlich nicht unterstellen - aber prüfe mal, ob Deine Aufgabenstellung wirklich nicht mit deutlich weniger SELECTs zu lösen ist. Denn ein SELECT _ist_ teuer, weil die Datenbank erst mal die 4GL in 3GL-Code übersetzen muß, und das womöglich immer wieder.
Wie steht es mit Host-Variablen? mySQL kann das m. E. noch nicht, aber vielleicht ist genau das Dein Problem?
Performance-Tuning bzw. Schwachstellenanalyse ist ein Job, der _sehr_ ins Detail geht, also _alle_ verfügbaren Informationen nutzen muß, um zu wirklich guten Ergebnissen zu führen. Gerade bei SQL lohnt sich diese Mühe aber viel mehr als irgendwo sonst - Du kannst hier durchaus mal zwei, drei, vier Zehnerpotenten (!) an Geschwindigkeit herausholen, wenn Du den richtigen Ansatz machst.
Ich habe auch nicht exakt verstanden, was das Problem Deiner Implementierung ist. Du schreibst, es sei die Zahl der SELECTs; Sven ist eher auf die Performance jedes einzelnen SELECTs eingegangen, was natürlich auch wichtig ist, aber an einer anderen Stelle des möglichen Problems ansetzt.
Erst nachdem hier alles ausgereizt ist, solltest Du die Idee, mySQL oder etwas Vergleichbares zu verwenden, verwerfen und etwas Eigenes implementieren.
Denn um damit dieselbe Performance und Stabilität zu erreichen, kannst Du eventuell Mannjahre (!) an Implementierungsaufwand verbraten. Das will sehr gut überlegt sein.
mittlerweile scheint apache nicht mehr mit mysql
kommunizieren zu können.
Der Apache kommuniziert doch überhaupt nicht mit der Datenbank ... nur die vom Apache gestarteten Anwendungsprogramme tun das ... oder was habe ich mißverstanden?
mittlerweile bekomme ich leider nur noch "die seite
kann nicht angezeigt werden."
Von wem? Was der Browser auswürfelt, ist egal.
Lies die Logfiles Deiner Server-Anwendunge - sowohl Apache als auch mySQL (oder was immer Du im Einsatz hast - ein vernünftiges Logging-Feature muß nämlich auch Deine memory-pool-Lösung besitzen, sonst kriegst Du sie nicht fehlerfrei).
wie gesagt: jede datenbank scheint mit der unmenge
an selects probleme zu bekommen.
Wie gesagt: Überprüfe Deinen Entwurf. Mußt Du wirklich so viele SQL-Statements ausführen?
alternativ - da auch mittlerweile einfacher zu
realisieren - zog ich ein filesystem in betracht;
files mit den entsprechenden einträgen werden dann
eben includiert - falls vorhanden - und - falls
nicht vorhanden - aus der DB ausgelesen, dann das
file geschrieben.
Das ist natürlich eine Alternative - wenn Deine Aufgabenstellung es zuläßt.
Du hast bisher nur über Deinen Realisierungsversuch geschrieben, bist aber sehr wenig darauf eingegangen, was Deine SELECT-Statements überhaupt _tun_.
Liest Du immer wieder dieselben Daten? Dann ist ein Caching-System natürlich durchaus eine Möglichkeit.
Darfst Du überhaupt cachen, oder mußt Du zeitaktuelle Werte aus der Datenbank entnehmen, weil parallel zu Deinen SELECTs jemand in diese Datenbank schreibt?
Das alles will überlegt sein, bevor Du Dich auf einen Implementierungspfad festlegst. Es ist ein Riesenunterschied, ob Du eine Datenbank als Transaktionssysten oder als Cache benutzt - und im letzteren Falle gibt es zweifellos performante Alternativen, und das _kann_ eventuell sogar etwas ganz Triviales in Dateiform sein.
- welche werte müsste ich nun definitiv im apache-
kernel erhöhen, die sich auf die anzahl der
reinzulegenden werte (arrays) von derzeit 2 Mio
beziehen? gibts hier irgendwo verständliche
informationen wie das zu handeln ist
Analog zu einem anderen Posting möchte ich Dir ans Herz legen, Deine Aufgabenstellung zu hinterfragen.
Es riechst alles danach, als ob Du mit einer anderen Vorgehensweise viel glücklicher wirst, als wenn Du an den Symptomen herumdokterst (genau das wäre nämlich das Einstellen irgendwelcher Speicher-Größenwerte).
- ist in meinem fall von dem SHM evtl. komplett
abzuraten und vielleicht doch ein "file-cache-
system" zu verwenden?
Vielleicht. Das kommt auf Deine Aufgabenstellung an.
Es ist auf jeden Fall das erste, was Du prüfen solltest.
Viele Grüße
Michael