web-development-kb-eu.site

Speichern vs. Berechnen von Aggregatwerten

Gibt es Richtlinien oder Faustregeln, um zu bestimmen, wann Aggregatwerte gespeichert und wann sie im laufenden Betrieb berechnet werden sollen?

Angenommen, ich habe Widgets, die Benutzer bewerten können (siehe Schema unten). Jedes Mal, wenn ich ein Widget anzeige, kann ich die durchschnittliche Benutzerbewertung aus der Tabelle Ratings berechnen. Alternativ könnte ich die durchschnittliche Bewertung in der Tabelle Widget speichern. Dies würde mich davon abhalten, die Bewertung jedes Mal berechnen zu müssen, wenn ich das Widget anzeige, aber dann müsste ich die durchschnittliche Bewertung jedes Mal neu berechnen, wenn ein Benutzer ein Widget bewertet.

Ratings       Widgets
---------     -------
widget_id     widget_id
user_id       name              
rating        avg_rating  <--- The column in question
100
BenV

Es kommt darauf an. Durch die Vorberechnung von Aggregatwerten werden Schreibvorgänge stärker belastet, deren Ableitung das Lesen erschwert.

Wenn Sie häufig auf einen abgeleiteten Wert zugreifen, ist die Vorberechnung ein gültiger De-Normalisierungsschritt. In diesem Fall empfehle ich jedoch die Verwendung einer materialisierten Ansicht (eine Ansicht, die auf die Festplatte geschrieben und durch Auslöser mit den übergeordneten Tabellen verknüpft ist). Die materialisierte Ansicht dient zum Speichern häufig angeforderter, aber mühsam abzuleitender Daten und ist nützlich für eine hohe Anzahl von Schreibvorgängen und eine geringe Anzahl von Lesevorgängen.

In einem Szenario mit hohem Schreib- und Lesezustand sollten Sie eine Aufgabe im Hintergrund haben, die die Auswirkungen einer materialisierten Ansicht nachahmt, jedoch weniger als in Echtzeit. Dies wird einen "gut genug" Durchschnitt darstellen, während die Schreib- und Leseleistung erhalten bleibt.

Unter keinen Umständen sollten Sie die abgeleitete Spalte wie eine "normale" Spalte behandeln: Stellen Sie sicher, dass die in der "Ansicht" der Widgets angezeigten Daten an anderer Stelle in der Tabelle vorhanden sind, sodass das gesamte Tupel von den von Ihnen gesetzten Prozessen abgeleitet werden kann. Diese Frage ist auch stark datenbankspezifisch (und datenbankversionsspezifisch). Ich empfehle daher, die Leistung des Aggregats (mit geeigneten Indizes) anhand eines Datensatzes normaler Größe und der materialisierten Ansicht zu testen.

60

Wie oft müssen Sie die Werte berechnen/anzeigen, relativ dazu, wie oft die zugrunde liegenden Zahlen geändert/aktualisiert werden.

Wenn Sie also eine Website mit 10.000 täglichen Treffern haben, auf der ein Wert angezeigt wird, der sich nur einmal pro Stunde ändert, würde ich ihn berechnen, wenn sich die zugrunde liegenden Werte ändern (könnte ein Datenbankauslöser sein, was auch immer).

Wenn Sie ein Tool haben, mit dem Sie Statistiken anzeigen können, bei denen sich die Statistiken von Sekunde zu Sekunde ändern, aber nur drei Personen Zugriff haben und diese nur ein paar Mal am Tag anzeigen, ist die Wahrscheinlichkeit höher, dass ich sie berechne es im laufenden Betrieb. (Es sei denn, es dauert ein paar Minuten, um zu berechnen, dass es keine große Sache ist, veraltete Daten zu haben ... und mein Chef sagt mir, ich soll das Ding nur jede Stunde aus Cron generieren, damit er es nicht hat warten, wenn er es sich ansehen will.)

11
Joe

Verwenden Sie die StaleWidgets-Tabelle als Warteschlange für "ungültige" (neu zu berechnende) Widgets. Verwenden Sie eine andere Thread-Task (asynchron), mit der diese Werte neu berechnet werden können. Zeitraum oder Zeitpunkt der Neuberechnung hängen von den Systemanforderungen ab:

  • nur beim lesen,
  • am Monatsende
  • für einige Benutzer zu Beginn des Tages
  • ...
4
garik

Ich würde empfehlen, im laufenden Betrieb zu berechnen, wenn die Berechnung nicht zu umständlich ist und wenn Sie komplexe Berechnungen und häufige Aktualisierungen durchführen, aber nicht das Frequnet lesen, als Sie berechnete Daten speichern können und eine zusätzliche Spalte (bool) haben, in der gespeichert wird, ob eine Neuberechnung erforderlich ist oder nicht . z.B. Setzen Sie diese Spalte auf true, wenn eine Neuberechnung durchgeführt werden soll, führen Sie jedoch keine Neuberechnung durch. Wenn Sie eine Neuberechnung durchführen, setzen Sie diese Spalte auf false (dies stellt dar, dass der berechnete Wert aktuell und nicht veraltet ist).

Auf diese Weise müssen Sie nicht jedes Mal neu berechnen. Sie berechnen nur, wenn Sie lesen müssen und der Wert der Neuberechnung der Spalte wahr ist. Auf diese Weise sparen Sie viel Neuberechnung.

2
techExplorer

Insbesondere für den Fall gibt es eine andere Lösung, bei der Sie nicht alle Bewertungen addieren und durch die Summe dividieren müssen, um den Durchschnitt zu ermitteln. Stattdessen können Sie ein anderes Feld verwenden, das die Summe der Bewertungen enthält. Jedes Mal, wenn Sie eine Bewertung hinzufügen, berechnen Sie den neuen Durchschnitt mit (avg_rating × total + new_rating)/total. Dies ist viel schneller als das Aggregat und reduziert die Festplattenwerte seit Ihnen Sie müssen nicht auf alle Bewertungswerte zugreifen. Ähnliche Lösungen könnten auch für andere Fälle gelten.

Der Nachteil dabei ist, dass es sich nicht um eine saure Transaktion handelt, sodass Sie möglicherweise mit einem veralteten Rating enden. Sie können dies jedoch mithilfe von Triggern in der Datenbank lösen. Das andere Problem ist, dass die Datenbank nicht mehr normalisiert ist, aber keine Angst davor hat, Daten im Austausch für die Leistung zu denormalisieren.

2
Adrian Martinez