Können SQLAlchemy-Ereignisse zum Aktualisieren eines denormalisierten Datencaches verwendet werden?

7

Aus Leistungsgründen habe ich eine denormalisierte Datenbank, in der einige Tabellen Daten enthalten, die aus vielen Zeilen in anderen Tabellen aggregiert wurden. Ich möchte diesen denormalisierten Datencache beibehalten, indem ich SQLAlchemy-Ereignisse verwende. Angenommen, ich schreibe Forumsoftware und möchte, dass jede Thread eine Spalte hat, die die kombinierte Wortzahl aller Kommentare im Thread verfolgt, um diese Informationen effizient anzuzeigen:

%Vor%

Jedes Mal, wenn ein Kommentar eingefügt wird (der Einfachheit halber sagen wir, dass Kommentare niemals bearbeitet oder gelöscht werden), möchten wir das word_count -Attribut für das zugehörige Thread -Objekt aktualisieren. Also würde ich etwas wie

machen wollen %Vor%

Wenn ich also Comment einfüge, kann ich die Ereignisauslösung sehen und sehen, dass sie die Wortzählung korrekt berechnet hat, aber diese Änderung wird nicht in der Thread -Zeile in der Datenbank gespeichert. In der after_insert werden keine Einschränkungen bezüglich aktualisierter anderer Tabellen angezeigt Dokumentation , obwohl ich in einigen anderen einige Vorbehalte sehe, wie zum Beispiel after_delete .

Gibt es eine unterstützte Möglichkeit, dies mit SQLAlchemy-Ereignissen zu tun? Ich verwende bereits SQLAlchemy-Ereignisse für viele andere Dinge, also möchte ich alles auf diese Weise tun, anstatt Datenbank-Trigger schreiben zu müssen.

    
Eli Courtwright 03.12.2012, 23:49
quelle

2 Antworten

33

Das after_insert () - Ereignis ist eine Möglichkeit, dies zu tun, und Sie werden möglicherweise feststellen, dass es ein SQLAlchemy Connection -Objekt statt eines Session übergeben hat, wie es bei anderen Flush-bezogenen Ereignissen der Fall ist. Die Flush-Ereignisse auf Mapper-Ebene sollen normalerweise verwendet werden, um SQL direkt auf dem angegebenen Connection aufzurufen:

%Vor%

Was hier bemerkenswert ist, ist, dass das direkte Aufrufen einer UPDATE-Anweisung viel leistungsfähiger ist als das erneute Ausführen dieser Attributänderung durch den gesamten Arbeitseinheitsprozess.

Allerdings ist ein Ereignis wie after_insert () hier nicht wirklich notwendig, da wir den Wert von "word_count" kennen, bevor der Flush überhaupt passiert. Wir kennen es tatsächlich, da Comment- und Thread-Objekte miteinander verknüpft sind, und wir könnten Thread.word_count jederzeit mit Hilfe von Attributereignissen vollständig im Speicher halten:

%Vor%

Der große Vorteil dieser Methode besteht darin, dass es auch nicht notwendig ist, thread.comments zu durchlaufen, was bei einer entladenen Sammlung bedeutet, dass ein anderer SELECT-Code ausgegeben wird.

noch eine andere Methode ist, es in before_flush () zu tun. Unten ist eine schnelle und schmutzige Version, die verfeinert werden kann, um genauer zu analysieren, was sich geändert hat, um zu bestimmen, ob das Wort_zählend aktualisiert werden muss oder nicht:

%Vor%

Ich würde mit der Methode der Attributsereignisse fortfahren, da sie am leistungsfähigsten und aktuellsten ist.

    
zzzeek 07.12.2012, 15:15
quelle
3

Sie können dies mit SQLAlchemy-Utils aggregated columns tun: Ссылка

    
mwhite 08.01.2015 02:20
quelle