Trigger statt PHP

Hallo,
Ich habe mal eine etwas grundsätzliche Frage bei der ich mir nicht ganz sicher bin.

ich habe in meiner Applikation eine Tabelle Gemeinden. In dieser Tabelle steht immer pro Gemeinde und pro Jahr ein Datenwert drin. Zusätzlich gibt es jetzt noch Aggregationen von den Gemeinden. d.h. bestimmte Gemeinden zusammen bilden dann den Kreis oder das Land. Der Datenwert für den kreis wäre also die Summe aus allen Datenwerten der zugehörigen Gemeinden. Immer wenn jetzt ein Datenwert für eine Gemeinde geändert wird, dann ändert sich natürlich auch der Datenwert für den Kreis und das Land. Jetzt zu meiner Frage. Bisher habe ich diese Summen immer im PHP errechnet. ich habe also die Summe abgefragt und dann wieder zurück geschrieben. Im Prinzip bin ich mir jetzt aber nicht sicher, ob es nicht viel sinnvoller wäre das Ganze direkt die Datenbank machen zu lassen über einen Trigger oder so. Damit würde ich mir dann ja den Traffic usw. sparen um das in Php zu machen. ich bin mir aber jetzt grundsätzlich nicht ganz sicher was da die bessere Idee ist. Eigentlich sollte die Datenbank ja immer schneller sein, als PHP und deshalb wäre es wahrscheinlich besser das die DB machen zu lassen, oder? oder spielt das gar keine Rolle wie man das macht? Kann mir da jemand vielleicht helfen und seine Meinung dazu erläutern? Was sind die jeweilige Vor- und Nachteile?
Für eure Hilfe bedanke ich mich wie immer recht herzlich im Voraus.

Gruss
hanno

Eine Grundregel beim Einsatz von relationalen Datenbanken: Information die sich aus bestehenden Daten ableiten lässt, muss nicht gespeichert werden.

Ich würde das weder in PHP noch in einem Trigger berechnen, sondern eine VIEW erstellen die diese Aggregation macht, irgendwas in der Art:

select kreis, sum(datenwert) as datenwert_total
from the_table
group by kreis

Bei vielen Datensätzen (Millionen) kann das eventuell langsam werden. Dann - und nur dann - sollte man solche Daten de-normalisiert abspeichern (wenn man mit normalen Turing-Maßnahmen nicht auf die gewünschte Geschwindigkeit kommt).

Je nachdem wie oft sich die Daten ändern kann man solche Aggregate auch als Materialized View erstellen, der dann z.B. bei Bedarf oder regelmässig aufgefrischt wird. Dann sind sie auch bei vielen Daten recht schnell. Geht ab PostgreSQL 9.3.

Gruß Uwe

Danke für die Anregungen,

Momentan habe ich etwa 400 Gemeinden für 10 Jahre. Dabei sind es etwa 1000 Indikatoren. Das sind momentan also schon etwa 4 Mio Datensätze. jedes Jahr kommen dann für jeden Indikator Datensätze dazu. Das wird also auf Dauer ganz schön viel. Aus diesem Grund hatte ich es eben extra abgespeichert, anstatt die Daten “zusammenzusetzen”. Ich dachte eben auch, dass es irgendwannd ann doch sehr langsam wird, und es eventuell schneller gehen würde wenn ich nur Datenwerte quasi direkt abfragen kann anstatt mit SQL Berechnungen “on-the-fly”. Für die Datenkonsitenz ist das natürlich blöd, da man ja eben immer darauf achten muss das alle Daten auch passen.
Ich habe jetzt aber keine Erfahrung, ob das dann wirklich zu lange dauert oder nicht. Gibt es da Richtwerte oder ist das einfach ausprobieren?

Gruss
Hanno

Ich dachte eben auch, dass es irgendwannd ann doch sehr langsam wird … Gibt es da Richtwerte oder ist das einfach ausprobieren?

Optimierung die auf “ich dachte”, oder “ich vermute” beruhen sind meistens keine gute Idee.

Eine Aggregation über 4 Millionen Datensätze ist jetzt nichts wirklich großes. Dafür wurden relationale Datenbanken gebaut. Mit einer einigermaßen vernünftigen Hardware und den passenden Indizes sollte das kein Problem sein. Antwortzeiten im Bereich unter 100 Millisekunden sind aber vermutlich nicht zu erwarten - ob das dann reicht musst Du ausprobieren.

Meine Strategie ist immer: einfach anfangen, kompliziert wird es dann von alleine. Ich würde also erst mal eine View erstellen. Wenn sich dann doch rausstellt, dass die zu langsam ist. Hängt es davon wie aktuell die Aggregation sein sollte. Wenn neue Werte sofort sichtbar sein sollen, dann ist vermutlich eine Tabelle + Trigger die richtige Wahl. Aber: das macht insert, updates und deletes auf die eigentlich Tabelle deutlich langsamer. Die Frage ist, was wichtiger ist: Lesegeschwindigkeit oder Schreibgeschwindigkeit. Ein Kompromiss wäre eine materialized view die z.B. jede Stunde aktualisiert wird.

Aber wie gesagt: teste es erst mal nur mit der View. Wenn das zu langsam wird, kann man die Abfrage tunen. Erst wenn das nichts mehr hilft würde ich zu einer der oben genannten Lösungen greifen. Wenn nicht immer über alle Jahre (und alle Indikator) aggregiert werden soll, hast Du sowieso keine andere Wahl.

Danke nochmals für die Antworten. Das hilft mir schonmal weiter. Vielen Dank für die immer sehr hilfreichen Antworten

Für mich ist " Meine Strategie ist immer: einfach anfangen," eigentlich ganz ähnlich wie “ich dachte”. :slight_smile:
Aber deshalb hab ich ja hier gefragt, bevor ich “einfach anfange”. Ich werde das aber jetzt mit ein paar Testdaten ausprobieren.
Ich habe aber noch eine weitere Frage. Was ist denn genau der Unterscheid zwischen einer “normalen” View und einer materialized View? Verstehe ich das richtig, dass eine MV immer eine ich nenn es mal “kopie” von den Daten (aus Selects, Joins usw.) vorhält und somit nicht immer das komplette SQL dahinter ausführen muss? Während eine Normale View bei jedem Aufruf immer die hinterlegten Tabellen abfragt und keine Daten in dem Sinne gespeichert werden?
D.h. wenn meine Daten sich nicht unbedingt ständig ändern, wäre eine MV geeignet, wenn es aber ständige Updates und aktuellste daten braucht dann sind die nicht so gut, weil man die MV dann ja immer refreshen müsste? Sorry für die vielen Fragen, ich hoffe ich nerve nicht. :slight_smile:

Gruss und vielen Dank
Hanno

Ja, so ist es.