Markus Stolpe M-T-S[AT]GMX.NET: Shared Memory / Semaphoren - Verständnisproblem

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?

  • welche werte (SHMMIN, SHMMAX, SHMALL, ...) habe ich bei dem server (apache/linux) zu ändern bei gesamt 2 Millionen+ eintragungen (beachte: sind schlussendlich in $arrays drin!)

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

  1. 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

    1. 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

      1. 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

    2. 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

  2. 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

    1. 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:

      • 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
      • ist in meinem fall von dem SHM evtl. komplett abzuraten und vielleicht doch ein "file-cache-system" zu verwenden?

      besten dank nochmals!

      Markus Stolpe

      1. 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

      2. 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

        1. 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

          1. 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

            1. 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

      3. 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