mixmastertobsi: temporäre Tabelle bei MySQL

Hallo,

ich habe bei mir ein paar SQL Abfragen, die relativ aufwändig sind, weshalb diese ein paar ms länger brauchen, allerdings die selbe Abfrage am Tag öfters aufgerufen wird. Ich habe bereits über Indexes das maximale rausgehgolt...

Momentan habe ich es so gelöst und frage mich, ob es hier ggf. Verbesserungsvorschläge gibt.

Die Abfrage wird erstellt und es wird als erstes in der "TEMP" Tabelle geschaut, ob hierzu etwas gespeichert ist. Wenn in der Tabelle etwas gespeichert ist, wird dieser Inhalt ausgegeben - wenn nicht, wird eben das Skript weiter bearbeitet und die "eigentliche" SQL-Abfrage wird gestartet und dann in der TEMP Tabelle gespeichert. Die Ergebnisse speicher ich dann in einem Array und codiere dies mit "json_encode". Einmal am Tag wird dann die Abfrage wieder gelöscht.

Wie gesagt - die Frage ist, ob man das so praktizieren kann und was Eure Meinung dazu ist.

  1. Tach!

    ich habe bei mir ein paar SQL Abfragen, die relativ aufwändig sind, weshalb diese ein paar ms länger brauchen, allerdings die selbe Abfrage am Tag öfters aufgerufen wird.

    Eigentlich hat MySQL einen Query-Cache, aus dem dieselbe Frage beantwortet werden kann. Ist für dessen Größe vielleicht bei dir Optimierungspotential?

    dedlfix.

    1. Hallo, den Cache nutzen wir bereits, aber dennoch kommt es vor, dass die Abfragen teilweise nicht aus dem Cache geladen werden. Ein Time-Limit kann ich ja beim Cache nicht einstellen, aber wenn ich zum Beispiel 2-3 Stunden nicht mehr die Abfrage gestartet hatte, nimmt er die Abfrage nicht mehr aus dem Cache, sondern startet die Abfrage neu.

      1. Hallo mixmastertobsi,

        aber wenn ich zum Beispiel 2-3 Stunden nicht mehr die Abfrage gestartet hatte, nimmt er die Abfrage nicht mehr aus dem Cache, sondern startet die Abfrage neu.

        Weil das DBMS bestimmt feststellt, dass sich die Datenbasis geändert hat.

        Bis demnächst
        Matthias

        --
        Dieses Forum nutzt Markdown. Im Wiki erhalten Sie Hilfe bei der Formatierung Ihrer Beiträge.
  2. Wie gesagt - die Frage ist, ob man das so praktizieren kann und was Eure Meinung dazu ist.

    Warum nicht? Bei statischen Ergebnissen kann sich das lohnen.

    Ich denke, Du machst es so:

    ...
    $Statement 'bauen'.
    Aus $Statement mit md5 $Hash bauen.
    $Dateiname aus $Hash bauen.
    Schauen ob es den Cache gibt.
    wenn nicht:
     Abfrage starten
     $Ergebnis mittels var_export oder serialize (json ist langsamer!) in Datei $Dateiname speichern.
    wenn ja:
     $Ergebnis aus Datei $Dateiname importieren
    :ende wenn
    Mit $Ergebnis arbeiten
    ...
    

    Dynamic: Teile davon lassen sich sich in eine eigene Routine auslagern und das Speicher des Caches nur durchführen, wenn die Abfrage mehr als n Millisekunden benötigte... microtime(true) liefert die Zeiten.

    weshalb diese ein paar ms länger brauche

    Wenn Du in Sachen Performance stark optimieren willst:

    Wenn es vorhersehbar SEHR viele (tausende) solcher Cache-Files geben wird, dann solltest Du im Auge behalten, dass bei vielen (auch Linux-) Dateisystemem die Performance in den Keller geht wenn in einem Verzeichnis SEHR viele (jedenfalls über 1000) Dateien sind. Dann wird die Zugriffszeit auf die Datei stark steigen. Es wird sich also lohnen, für den cache eine Verzeichnisstruktur einzurichten:

    Das kann so gehen:

    Baue mit Stringfunktionen aus einem Hash "aee97cb3ad288ef0add6c6b5b5fae48a" sowas

    # $sqlCacheDir = '/tmp'
    # $sHash = "aee97cb3ad288ef0add6c6b5b5fae48a"
    # $CacheDirLevel = 4;
    
    $arHash = explode( '', $sHash, $CacheDirLevel );
    $cacheFileName = $sqlCacheDir . implode( '/', $arHash );
    
    # Ergebnis: $cacheFileName == '/tmp/a/e/e/97cb3ad288ef0add6c6b5b5fae48a';
    
    1. Ob man einen Cache im Filesystem hält, in einer DB-Row (wie es der OP beschrieben hat) oder auf einem eigenen Cache-Server, hängt sicherlich vom Anwendungsfall ab.

      Hat man nur einen Applicationserver (möglicherweise sogar einen, auf dem Web+App zusammenfallen), ist das Filesystem die beste Wahl. Die serialisierten Ergebnisse im SQL Server zu speichern ist eigentlich eine unnötige Belastung für ihn. Dem Einwand mit zu vielen Dateien kann man durch scharfes Überlegen begegnen, welche Queries denn so gecached werden sollen. Oder man verteilt es in mehrere Verzeichnisse und hat in einem Verzeichnis nur die Ergebnisse einer Query (in einer Datei je Parametersatz).

      Hat man einen Server-Cluster, ist Filesystem ungünstig, weil dann jeder Server für sich cached. Dann ist die Cache-Table mit serialisierten Abfrageergebnissen ein Cache-Server für arme Leute und bringt dadurch etwas, dass die komplexen Abfragewege der eigentlichen Query eingespart werden. Aber eine SQL Last ist es immer noch. Ein richtiger Cache-Server (wo die Daten im RAM oder als Dateien im Filesystem gehalten werden) würde die DB stärker entlasten. Aber das setzt eine entsprechend große Farm voraus, sonst lohnt das nicht.

      WENN Deine Daten so geartet sind, dass ein Caching mit einem Tag Verfallsfrist machbar ist, dann hast Du auch noch eine andere Möglichkeit: prepared data. Du kannst die Tabellen, die deine "langsamen" Queries abfragen, ggf. in andere Tabellen transformieren. Diese anderen Tabellen könnten dann Redundanzen enthalten, oder bereits vorbereitete Zwischensummen haben - was man tun kann hängt sehr vom konkreten Fall ab. Wenn das Ergebnis der Transformation darin besteht, dass die langsame Query nicht mehr 500ms, sondern 5ms braucht, kann sich die Sache lohnen. Die prepared data Tabellen könntest Du dann jeden Morgen um 5 Uhr (oder so) einmal befüllen. Ist nur so ein Gedanke...

      Rolf