T-Rex: Summaryfelder

Moin,

hab da mal eine grundsätzliche Frage.
Und zwar hab ich da einen Datensatz. Dieser Datensatz hat in der Datenbank ein paar Statistiken (n:m). Die Statistiken ändern sich nicht sehr häufig. Diese Abfragen sind relativ Performancelastig. Da der Datensatz eher gelesen als geschrieben wird, habe ich Summaryfelder in die Tabelle eingebaut. Also immer wenn der Datensatz gespeichert wird, werden die Statistiken neu berechnet und in die Summaryfelder geschrieben. Somit kann ich später einfach darauf zugreifen ohne das diese bei jeder Abfrage neu berechnet werden, was nebenbei auch die Querys erheblich vereinfacht.

Jetzt ist natürlich das Problem, wenn sich doch mal etwas ändert. Dann müssen nämlich alle Hauptsätze nochmals speichern, damit die Summaryfelder aktualisiert werden.

Gibt es vielleicht eine Alternative?
Views scheiden aus ;).

Gruß
ausscheidender
T-Rex

  1. "speichern" musst du die Hauptsätze ja nicht, nur aktualisieren.
    Das könntest du auch in einer separaten Tabelle tun, falls du die Datensätze lieber in Ruhe lassen willst.
    Evtl. kannst du auch je nach Änderung nur bestimmte Statistikfelder, oder auch nur bestimmte Datennsätze aktualisieren? Nämlich nur die wirklich betroffenen.
    Oder du rechnest die geänderten Daten in die Statistiken hinein, anstatt alles nochmal neu auszurechnen. Sofern das die Daten hergeben, wir kennen sie ja nicht.

    1. Joa die Hauptdatensätze können schon gespeichert werden, dass ist kein Problem. Mir geht es eher darum zu wissen wann diese Gespeichert werden sollen.

      Ändere ich etwas an einem Kinddatensatz, dann müssen alle Hauptdatensätze aktualisiert werden. Da eine n:m Verbindung vorherrscht können das extrem viele Speicherungen werden.
      Ergo hab ich an einen Cronjob gedacht, der guckt welche Kinddatensätze haben sich "heute" geändert und lässt eine Speicherung in der Nacht laufen. Ich mag aber keine Cronjobs. Die haben etwas magisches, etwas verstecktes.

      Gruß
      wenn ein Kinddatensatz gelockt ist, ist das dann ein Kinderriegel?
      T-Rex

      1. Tach!

        Ich mag aber keine Cronjobs. Die haben etwas magisches, etwas verstecktes.

        Du magst keine Automatismen wegen ihrer Unkontrollierbarkeit? Nun das kann man ändern. Kommandozeilenprogramme geben nach ihrer Abarbeitung üblicherweise einen Status aus, den man prüfen kann. Deutet dieser auf einen Fehler hin, dann Mail an den Admin senden. Cronjobs bilden da keine Ausnahme. Das Problem sind dann nur noch Automatismen, die still und leise nicht wie gewünscht arbeiten. Das ist dann ein Problem der Organisation. Von der durch den Automatismus gesparten Zeit muss ein Teil zu dessen Kontrolle abgezogen werden. Solch eine Kontrolle muss nicht jeden Arbeitsschritt des Automatismus nachvollziehen, aber sich wenigstens eine Übersicht über Normal- und Abnormalitäten verschaffen können. Wenn diese Kontrolle nicht organisiert werden kann, hat der Admin und/oder seine organisatorische Struktur Verbesserungspotential.

        dedlfix.

        1. na klar, du hast ja recht.
          Man kann aber nicht für jeden Scheiß einen Cronjob machen. Halte ich auch für keinen guten Stil. Mein Vorgänger hier in der Firma hatte so ca. 30 Cronjobs für ein Portal jede Nacht laufen. Der erste wurde 0 Uhr aufgerufen, der letzte um 5 Uhr. Keine Ahnung wie lang die wirklich liefen, trotzdem halte ich das nicht für gut.

          Wenn alle Stricke reißen werde ich wohl einen Cronjob machen, bis dahin hab ich aber Hoffnung, dass es eventuell eine andere Möglichkeit gibt.

          Gruß
          Cronjob Ersetzer
          T-Rex

          1. Tach!

            Wenn alle Stricke reißen werde ich wohl einen Cronjob machen, bis dahin hab ich aber Hoffnung, dass es eventuell eine andere Möglichkeit gibt.

            Die beiden mir einfallenden Möglichkeiten wurden ja schon genannt: Cronjob als unabhängiger Automatismus und Trigger als abhängiger Automatismus.

            dedlfix.

  2. હેલો

    Da der Datensatz eher gelesen als geschrieben wird, habe ich Summaryfelder in die Tabelle eingebaut. Also immer wenn der Datensatz gespeichert wird, werden die Statistiken neu berechnet und in die Summaryfelder geschrieben. Somit kann ich später einfach darauf zugreifen ohne das diese bei jeder Abfrage neu berechnet werden, was nebenbei auch die Querys erheblich vereinfacht.

    Könntest du vielleicht in ein Paar einfachen Worten erklären, wozu das gut ist, warum man das macht? Ich kann damit komplett nichts anfangen, also bitte Noob-Gerecht ;)

    બાય

    --
     .
    ..:
    1. Könntest du vielleicht in ein Paar einfachen Worten erklären, wozu das gut ist, warum man das macht? Ich kann damit komplett nichts anfangen, also bitte Noob-Gerecht ;)

      Also die Theorie der Datenbank hat ja die 5 Normalisierungstufen. Grob gesagt schiebt man die Inhalte von einer Tabelle in mehrere Tabellen und verknüpft das ganze über Schlüssel (Foreignkeys). Damit erhofft man sich Redundanzen zu umgehen. Das Problem ist dann natürlich wieder das Verknüpfen bei einer Abfrage, denn du musst die Tabellen joinen.

      Jetzt nehmen wir mal an es wird ein Rating von einem Datensatz ausgerechnet. Am Ende kommt also eine Zahl zwischen 0 und 10 raus. 0 ist schlecht und 10 ist super. Als Grundlage für diese Zahl eines Datensatzes (z.B. "wie beliebt ist der Film") dienen insgesamt 1500 Datensätze in 20 Tabellen. Da ist eine Tabelle mit Views, also wie oft wurde die Webseite mit diesem Film aufgerufen, wie oft runter geladen, Bewertung im klassischen sinne etc...

      Damit man diese 1500 Datensätze bzw. 20 Tabellen nicht bei jedem Aufruf anzapfen muss, baut man gewollte Redundanzen ein. Beim speichern (als Beispiel) des Hauptdatensatzes wird eben doch mal die Berechnung durchgeführt um dann das ergebnis in einem Tabellenfeld zu speichern. Somit hat man die Zahl (Rating in diesem Fall) bei jedem Query dabei um muss sie nicht jedes mal ausrechnen. Um genau zu sein erkauft mans ich Abfrage-Performance durch mehr speicherplatz und eine langsamere Speicherung. Da Webseiten in der Regel aber öfter angefragt werden als dass man Daten speichert ist das in der Regel auch okay.

      Um bei dem Beispiel zu bleiben ist mein Problem (wobei PRoblem ist es ja nicht wirklich, es ist eine logische Konsequenz) dass die Daten unter umständen nciht aktuell sind. Nehmen wir mal an von den 20 Tabellen verschwindet eine. Die wird einfach gelöscht, da sie nicht mehr gebraucht wird. Das Rating würde sich von 4.2 auf 3.7 ändern. Aber nur, wenn man den Hauptdatensatz nochmals abspeichert, denn beim speichern liegt ja wie beschrieben die Logik die Redundanz zu berechnen und in das Summaryfeld zu schieben.
      Also hat man unter umständen veraltete Daten. In meinem Fall wäre das nicht soooo tragisch, da die Daten nicht relevant sind. Ähnlich wie bei dem Film. Ob der jetzt 3.7 hat oder 4.2 juckt wahrscheinlich niemand.

      Dennoch frage ich mich gerade ob es eine Elegante Lösung gibt, die beide Seiten vereint.

      Gruß
      der sich einen Wolf schriebende, nicht mehr Korrektur lesende, da ihm die Augen gleich zufallen und somit auf Verständnis hoffende
      T-Rex (mit einer Rekord Signatur)

      1. હેલો

        Damit man diese 1500 Datensätze bzw. 20 Tabellen nicht bei jedem Aufruf anzapfen muss, baut man gewollte Redundanzen ein. Beim speichern (als Beispiel) des Hauptdatensatzes wird eben doch mal die Berechnung durchgeführt um dann das ergebnis in einem Tabellenfeld zu speichern. Somit hat man die Zahl (Rating in diesem Fall) bei jedem Query dabei um muss sie nicht jedes mal ausrechnen.

        Danke für die Ausführliche Antwort, hatte mit etwas komplizierterem gerechnet. So etwas in der Richtung wollte ich für eine Navigation realisieren, die aus einer Datenbank ausgelesen und zusammen gesetzt wird. Vielleicht hole ich das mal nach.

        der sich einen Wolf schriebende, nicht mehr Korrektur lesende, da ihm die Augen gleich zufallen und somit auf Verständnis hoffende

        Alles angekommen, alles ok ;)

        બાય

        --
         .
        ..:
      2. Tach!

        Um bei dem Beispiel zu bleiben ist mein Problem (wobei PRoblem ist es ja nicht wirklich, es ist eine logische Konsequenz) dass die Daten unter umständen nciht aktuell sind. Nehmen wir mal an von den 20 Tabellen verschwindet eine. Die wird einfach gelöscht, da sie nicht mehr gebraucht wird.

        Solch ein Szenario ist normalerweise nicht alltäglich. Das ist eine strukturelle Änderung der Datenbank, bei der vorher überprüft werden muss, welche Konsequenzen das für den Datenbestand hat und welche Maßnahmen zu unternehmen sind. Solch ein Löschen fängt auch kein Trigger ab. Bei diesem Szenario gibt es keine allgemeingültige technische Lösung des Konfliktes - ich wüsste jedenfalls keine.

        dedlfix.

        1. Dann war es einfach nur ein blödes Beispiel :).

          Gruß
          Blöder
          T-Rex

  3. Moin,

    hab da mal eine grundsätzliche Frage.
    Und zwar hab ich da einen Datensatz. Dieser Datensatz hat in der Datenbank ein paar Statistiken (n:m). Die Statistiken ändern sich nicht sehr häufig. Diese Abfragen sind relativ Performancelastig.

    Hier sollte Deine Optimierung ansetzen. Guck Dir die Queries mit explain an, dann siehst Du auch, wo ein Index nützlich sein könnte.

    Wenn per RDBMS mit Daten gerechnet wird, das ist nicht das Performance-Problem.
    Darüber hinaus kannst Du Updates auch triggern und die Ergebnisse in weiteren Tabellen ablegen.

    Grüße aus München,
    Horst Ländlich

    1. Hier sollte Deine Optimierung ansetzen. Guck Dir die Queries mit explain an, dann siehst Du auch, wo ein Index nützlich sein könnte.

      Für diese Optimierung sind die Daten die ich da raushole (also die Statistiken) zu nutzlos. Ist ja nur ein nice to see.

      Wenn per RDBMS mit Daten gerechnet wird, das ist nicht das Performance-Problem.

      Naja im großen und ganzen hast du da schon recht. Ich glaube mein Haupt Augenmerkt liegt eher auf einem einfachen und verständlichem Query. Ganz nebenbei spart man dann aber doch durch die Summaryfelder abfrage Zeit.

      Darüber hinaus kannst Du Updates auch triggern und die Ergebnisse in weiteren Tabellen ablegen.

      Trigger höre ich nur ungern. Das letzte größere Datenbankpoblem das ich hatte war ein Trigger Problem. Hab Trigger eingerichtet und die haben auch das gemacht was sie sollten. Dann kam ein Datenbankumzug, da mein Packet beim Provider ein Update bekam. Keine Ahnung was die gemacht haben, danach haben die Trigger nicht mehr funktioniert. MEine Erklärung damals, war dass die Trigger dem Datenbank Benutzer zugeordnet sind. Der hat sich anscheinend geändert. Der neue Benutzer hatte nicht mehr die Rechte diese Trigger auszuführen und so bekam ich jedes mal wenn ein Trigger angestossen wurde einen Fehler. Da muss man auch erstmal drauf kommen.

      Gruß
      Trigger Vernichter
      T-Rex

    2. Tach!

      hab da mal eine grundsätzliche Frage.
      Und zwar hab ich da einen Datensatz. Dieser Datensatz hat in der Datenbank ein paar Statistiken (n:m). Die Statistiken ändern sich nicht sehr häufig. Diese Abfragen sind relativ Performancelastig.
      Hier sollte Deine Optimierung ansetzen. Guck Dir die Queries mit explain an, dann siehst Du auch, wo ein Index nützlich sein könnte.

      Wenn ich mich recht erinnere, war es in seinem Fall bereits ein mittelschweres Problem, die Abfragen entsprechend dem gewünschten Ergebnis zu formulieren. Da war mit Indexen nicht viel zu gewinnen. Deswegen hat er ja nun die nichtnormlisierte Form mit den Summary-Feldern, weil sich das wesentlich leichter handhaben lässt.

      Wenn per RDBMS mit Daten gerechnet wird, das ist nicht das Performance-Problem.

      So pauschal gesagt ist das nicht richtig. Wenn in der WHERE-Klausel ein zu berechnender Ausdruck als Bedingung steht, muss dieser Ausdruck für jede Zeile berechnet werden. Und ein Index kann dafür nicht herangezogen werden, weil es keine berechneten Indexe gibt. (dBase konnte das früher.) Bei vielen Datensätzen oder auch sehr vielen Abfragen bei weniger Datensätzen kann das sehr wohl zum Problem werden.

      Darüber hinaus kannst Du Updates auch triggern und die Ergebnisse in weiteren Tabellen ablegen.

      Das wäre eine Möglichkeit, den Hauptdatensatz gezielt neu berechnen zu lassen. Bedingung ist, dass die Unterdatensätze jeweils einen Verweis auf den Hauptdatensatz enthalten.

      dedlfix.

      1. Tach,

        So pauschal gesagt ist das nicht richtig. Wenn in der WHERE-Klausel ein zu berechnender Ausdruck als Bedingung steht, muss dieser Ausdruck für jede Zeile berechnet werden. Und ein Index kann dafür nicht herangezogen werden, weil es keine berechneten Indexe gibt. (dBase konnte das früher.) Bei vielen Datensätzen oder auch sehr vielen Abfragen bei weniger Datensätzen kann das sehr wohl zum Problem werden.

        Postgres kann das auch heute noch - http://www.postgresql.org/docs/9.2/static/indexes-expressional.html - aber T-Rex nutzt ja Mysql, IIRC. Aber auch damit tritt natürlich das selbe Problem auf, dass ein Insert oder Update teuer wird.

        mfg
        Woodfighter

      2. hi,

        Wenn ich mich recht erinnere, war es in seinem Fall bereits ein mittelschweres Problem, die Abfragen entsprechend dem gewünschten Ergebnis zu formulieren. Da war mit Indexen nicht viel zu gewinnen. Deswegen hat er ja nun die nichtnormlisierte Form mit den Summary-Feldern, weil sich das wesentlich leichter handhaben lässt.

        Aha ;)