PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Django + Postgres + Große Zeitreihen

Wenn ich Ihre Gedanken richtig verstehe, erwägen Sie, die Zeitreihen in PostgreSQL zu speichern, einen Zeitreihendatensatz in einer Datenbankzeile. Tun Sie das nicht.

Einerseits ist das Problem ein theoretisches. Relationale Datenbanken (und ich denke, die meisten Datenbanken) basieren auf der Prämisse der Zeilenunabhängigkeit, während die Datensätze einer Zeitreihe physisch geordnet sind. Natürlich bieten Datenbankindizes eine gewisse Ordnung für Datenbanktabellen, aber diese Ordnung soll die Suche beschleunigen oder die Ergebnisse alphabetisch oder in einer anderen Reihenfolge präsentieren; es impliziert keine natürliche Bedeutung für diese Reihenfolge. Unabhängig davon, wie Sie sie bestellen, ist jeder Kunde unabhängig von anderen Kunden, und der Kauf jedes Kunden ist unabhängig von seinen anderen Einkäufen, selbst wenn Sie sie insgesamt chronologisch erhalten können, um die Kaufhistorie des Kunden zu bilden. Die gegenseitige Abhängigkeit von Zeitreihenaufzeichnungen ist viel stärker, was relationale Datenbanken ungeeignet macht.

In der Praxis bedeutet dies, dass der von der Tabelle und ihren Indizes belegte Speicherplatz enorm sein wird (vielleicht 20-mal größer als das Speichern der Zeitreihen in Dateien) und das Lesen von Zeitreihen aus der Datenbank sehr langsam sein wird, so etwas wie eine Bestellung um Größenordnungen langsamer als das Speichern in Dateien. Es wird Ihnen auch keinen wichtigen Nutzen bringen. Wahrscheinlich werden Sie niemals die Abfrage „Gib mir alle Zeitreihendatensätze, deren Wert größer als X ist“ stellen. Wenn Sie jemals eine solche Abfrage benötigen, benötigen Sie auch eine Menge anderer Analysen, für deren Durchführung die relationale Datenbank nicht ausgelegt ist, sodass Sie sowieso die gesamte Zeitreihe in ein Objekt einlesen werden.

Daher sollte jede Zeitreihe als Datei gespeichert werden. Es kann entweder eine Datei im Dateisystem oder ein Blob in der Datenbank sein. Trotz der Tatsache, dass ich letzteres implementiert habe, glaube ich, dass ersteres besser ist; in Django würde ich so etwas schreiben:

class Timeseries(models.model):
    name = models.CharField(max_length=50)
    time_step = models.ForeignKey(...)
    other_metadata = models.Whatever(...)
    data = models.FileField(...)

Verwendung eines FileField wird Ihre Datenbank verkleinern und es einfacher machen, inkrementelle Backups Ihres Systems zu erstellen. Es wird auch einfacher sein, Slices zu erhalten, indem man in der Datei sucht, etwas, das mit einem Blob wahrscheinlich unmöglich oder schwierig ist.

Was für eine Datei? Ich würde dir raten, einen Blick auf Pandas zu werfen. Es ist eine Python-Bibliothek für mathematische Analysen, die Zeitreihen unterstützt und auch eine Möglichkeit haben sollte, Zeitreihen in Dateien zu speichern.

Ich habe oben auf eine meiner Bibliotheken verlinkt, deren Verwendung ich Ihnen nicht empfehle; Einerseits macht es nicht das, was Sie wollen (es kann keine Granularität feiner als eine Minute handhaben, und es hat andere Mängel), und andererseits ist es veraltet - ich habe es vor Pandas geschrieben, und ich beabsichtige, es zu konvertieren in Zukunft Pandas zu verwenden. Es gibt ein Buch, „Python for data analysis“, vom Autor von Pandas, das ich für unschätzbar wertvoll halte.

Aktualisierung (2016): Es gibt auch InfluxDB. Ich habe es nie verwendet und habe daher keine Meinung dazu, aber es ist definitiv etwas, das Sie untersuchen müssen, wenn Sie sich fragen, wie Zeitreihen gespeichert werden sollen.

Aktualisierung (2020-02-07): Es gibt auch TimescaleDB, eine Erweiterung von PostgreSQL.

Aktualisierung (2020-08-07): Wir haben unsere Software (erneut) so geändert, dass sie die Daten in der Datenbank mit TimescaleDB speichert. Wir kennen uns bereits mit PostgreSQL aus und es war einfach, etwas TimescaleDB zu lernen. Der wichtigste konkrete Vorteil ist, dass wir Abfragen wie „Finde alle Orte, an denen es 2019 innerhalb von 24 Stunden>50 mm Regen gab“ machen können, was bei der Speicherung von Daten in Flatfiles sehr schwierig wäre. Ein weiterer Vorteil sind die Integritätsprüfungen – im Laufe der Jahre hatten wir ein paar Zeitreihen mit doppelten Zeilen wegen hier und da kleiner Fehler. Auch die Nachteile sind erheblich. Es verbraucht 10-mal mehr Speicherplatz. Aus diesem Grund müssen wir möglicherweise unsere PostgreSQL-Sicherungsrichtlinie ändern. Es ist langsamer. Es dauert vielleicht eine Sekunde, um eine Zeitreihe mit 300.000 Datensätzen abzurufen. Dies war unmittelbar zuvor. Wir mussten Caching zum Abrufen von Zeitreihen implementieren, was vorher nicht benötigt wurde.