Ankündigung

Einklappen
Keine Ankündigung bisher.

SELECT- & INSERT-Befehle trennen

Einklappen

Neue Werbung 2019

Einklappen
X
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • SELECT- & INSERT-Befehle trennen

    Hallo zusammen,

    mir wurde von meinem Serverbetreiber empfohlen, lesende und schreibende Zugriffe auf die MySQL-Datenbank voneinander zu trennen. Diese Idee gefällt mir und wird mit Sicherheit einiges an Performance bringen.

    Wie macht man es denn nun richtig?
    Kennt sich jemand damit aus?

    Ich habe vorher selber recherchiert und habe Lösungsansätze gefunden.
    1. 2 identische Tabellen
    2. eine (NUR)-Lesetabelle und eine Schreibtabelle
    3. Die Schreibtabelle regelmäßig in die Lesetabelle kopieren (blockiert das nicht auch die SELECTs?)

    Da ich auch die Session-Daten in der Datenbank speichere, kann ich hier z.B. keine Trennung von Lese- und Schreibzugriffen vornehmen, da die wirkliche Speicherung der Daten ja zeitversetzt kommt (bei dem Beispiel oben).

    Also meine Frage: Gibt es eine Möglichkeit, lesende und schreibende Zugriffe auf bestimmten Tabellen zu trennen, und wie realisiert man dies am besten?

    Danke für Eure Hilfe.

  • #2
    Etwas konkreter bitte, so allgemein gibt es da wohl kaum eine Lösung.

    Kommentar


    • #3
      ...

      Gehen wir mal davon aus, wir haben eine Tabelle mit 1,5 Millionen Einträgen.
      Auf 2 Feldern gibt es einen Index. Wenn diese Tabelle stark frequentiert wird, dann wirken sich UPDATEs und INSERTs negativ auf die normalen SELECTs aus, denn sie werden unterdrückt, solange der Schreibprozess läuft. Dadurch, dass Indexes auf Feldern sind, dauert der Schreibprozess sogar noch etwas länger als normal. Wenn nun die Tabelle beim Schreiben zum Lesen blockiert ist, sammeln sich natürlich die wartenden SELECTs und das kann bei großen Datenbanken den MySQL-Server den Rest geben. Er schaukelt sich einfach hoch, bis nichts mehr geht.

      Also wurde mir geraten, die Schreibprozesse von den Leseprozessen zu trennen.

      Nur, wie realisiert man das am besten!? Natürlich kann ich jetzt hingehen, und 2 identische Tabellen pflegen. Eine zum Lesen und eine zum Schreiben, und diese dann mit
      PHP-Code:
      SELECT FROM tabelle1 INTO OUTFILE '/tmp/tabelle1.txt';
      LOAD DATA INFILE '/tmp/tabelle1.txt' INTO TABLE tabelle2
      synchronisieren. Aber ist das auch die optimalste Lösung. Voraussetzung ist hier: Es gibt nur EINEN MySQL-Server. Eine Replikation auf einen Slave-Server ist also ausgeschlossen.

      Ich hoffe, ich konnte mich verständlich ausdrücken und hoffe auf Eure Hilfe. Danke.

      Kommentar


      • #4
        Vorneweg: Ich habe nur gefährliches Halbwissen .

        Ich kann mir nicht vorstellen wie du mit nur einem Server und 2 Tabellen - eine fürs schreiben und eine fürs lesen die Performance steigern willst - schließlich musst du letzendlich auch in die "Lesetablle" schreiben....

        Das ganze bringt dir nur dann Performance-Vorteile wenn du in der "Lese-Tabelle" keine aktuellen Daten brauchst und so die aktualisierung auf einen zeitpunkt legen kannts zu dem wenig los ist (also nachts oder so...).

        Außerdem bin ich mir nicht einmal sicher ob bei einem Insert/Update die gesamte Tabelle überhaupt automatisch einen LOCK erhält....
        Falls ja habe ich irgendwie im Hinterkopf, dass bei InnoDB zeilenweise gelockt wird....

        Du kannst dir auch mal INSERT DELAYED anschauen....



        Wie gesagt verstehe ich nicht ganz wie das ganze einen Performance-Gewinn bringen soll....
        [URL="https://www.quizshow.io/"]Create your own quiz show.[/URL]

        Kommentar


        • #5
          Bis die "neuen" Aktionen in die Lesetabelle übertragen wurden, rufst Du immer veraltete Daten ab. Für ein Forum als Beispiel ist das dann natürlich nicht optimal. Wen Du eine große Tabelle (viele Felder, viele Datensätze) hast und eine geringe Anzahl Felder sich häufig ändert und der Rest sehr statisch ist bzw nicht immer alle Werte benötigt werden, kann es in der Tat sinnvoll sein, die Tabelle zu trennen. Aber nur im Einzelfall.
          Um welche Größenordnungen handelt es sich eigentlich (oder glaubst Du handelt es sich)? Wieviele Datensätze werden gespeichert? Wie groß ist ein Datensätz im Schnitt? Wie lange dauert ein INSERT und wieviele SELECT müssen deshalb warten? Bei welcher Belastung bricht dann der Mysql Server zusammen?

          Kommentar


          • #6
            ...

            Gehen wir einmal davon aus, das wir ein redaktionelles System mit 1,5 Millionen Artikeln haben. Diese Artikel werden haupsächlich nur gelesen, ABER jeder Aufruf des Artikels erhöht den Aufrufzähler um +1.
            Das bedeutet, das JEDER SELECT auch ein UPDATE mit sich zieht.

            Ich habe mich bereits von MYISAM getrennt und bin auf INNODB umgestiegen, da die INNODB zeilenweise und nicht tabellenweise lockt.

            Trotdem könnte man hier auch hingehen, und die Aufrufe in einer separaten Tabelle speichern, und diese dann gelegentlich via Cronjob aktualisieren.

            Richtig ist aber auch, dass man nicht immer Lese- und Schreiboperationen trennen kann.
            Doch muss man eine Lösung finden, dass auch etwas anspruchsvolle Datenbanken ohne NDB-Cluster-Systeme auskommen!??

            Was meint Ihr?

            Kommentar


            • #7
              Ich würde da eher mal versuchen von der anderen Seite aus ranzugehen, will sagen: Versuche dir einfach möglichst viele Anfragen an die DB zu sparen, indem du, statt die Daten jedesmal aus der DB zu lesen, einen Cache verwendest.
              Eine andere Idee habe ich momentan nicht.
              [URL="https://www.quizshow.io/"]Create your own quiz show.[/URL]

              Kommentar


              • #8
                Ja, das ist so ein Beispiel von "eine geringe Anzahl Felder sich häufig ändert und der Rest sehr statisch ist bzw nicht immer alle Werte benötigt werden".
                Ob man die Werte per cronjob wieder in die Haupttabelle zurück führt, ist eine andere Frage. Ich würde es erstmal mit einem JOIN probieren.
                Also verkürzt:
                artikel: artikel_id, verfasser, datum, teaser, primary key(id)
                artikel_inhalt: artikel_id, inhalt, unique key(artikel_id)
                artikel_counter: artikel_id, value, unique key(artikel_id)

                Code:
                SELECT a.verfasser, a.datum, b.value
                FROM artikel as a JOIN artikel_counter as b
                ON a.artikel_id=b.artikel_id

                Kommentar

                Lädt...
                X