Ich schreibe eine Anwendung, die große Mengen an elektrischen und Temperaturdaten speichern und analysieren muss.
Grundsätzlich muss ich große Mengen an stündlichen Stromverbrauchsmessungen für die letzten Jahre und für viele Jahre für Zehntausende von Standorten speichern und dann die Daten auf nicht sehr komplexe Weise analysieren.
Die Informationen, die ich (vorerst) speichern muss, sind Standort-ID, Zeitstempel (Datum und Uhrzeit), Temperatur und Stromverbrauch.
Bezüglich der Menge der Daten, die gespeichert werden müssen, handelt es sich um eine Annäherung, aber in diesem Sinne:
20 000+ Standorte, 720 Datensätze pro Monat (stündliche Messungen, ungefähr 720 Stunden pro Monat), 120 Monate (vor 10 Jahren) ) und viele Jahre in die Zukunft. Einfache Berechnungen ergeben folgende Ergebnisse:
20 000 Standorte x 720 Datensätze x 120 Monate (10 Jahre zurück) = 1 728 000 000 Datensätze .
Dies sind die bisherigen Datensätze. Neue Datensätze werden monatlich importiert. Das sind ungefähr 20.000 x 720 = 14.400.000 neue Datensätze pro Monat .
Auch die Gesamtstandorte werden stetig wachsen.
Für all diese Daten müssen die folgenden Vorgänge ausgeführt werden:
- Abrufen der Daten für ein bestimmtes Datum UND einen bestimmten Zeitraum: Alle Datensätze für eine bestimmte Standort-ID zwischen dem 01.01.2013 und dem 01.01.2017 sowie zwischen 07:00 und 13:00 Uhr.
- Einfache mathematische Operationen für einen bestimmten Datums- UND Zeitbereich, z. B. MIN-, MAX- und AVG-Temperatur und Stromverbrauch für eine bestimmte Standort-ID für 5 Jahre zwischen 07:00 und 13:00 Uhr.
Die Daten werden monatlich geschrieben, aber (mindestens) von Hunderten von Benutzern ständig gelesen, sodass die Lesegeschwindigkeit von wesentlich größerer Bedeutung ist.
Ich habe keine Erfahrung mit NoSQL-Datenbanken, aber nach dem, was ich gesammelt habe, sind sie die beste Lösung, um sie hier zu verwenden. Ich habe die beliebtesten NoSQL-Datenbanken gelesen, aber da sie sehr unterschiedlich sind und auch eine sehr unterschiedliche Tabellenarchitektur zulassen, konnte ich nicht entscheiden, welche Datenbank die beste ist.
Meine Hauptentscheidungen waren Cassandra und MongoDB, aber da ich nur sehr begrenzte Kenntnisse und keine wirkliche Erfahrung in Bezug auf große Datenmengen und NoSQL habe, bin ich mir nicht ganz sicher. Ich habe auch gelesen, dass PostreSQL auch mit solchen Datenmengen gut umgehen kann.
Meine Fragen sind folgende:
- Sollte ich eine NoSQL-Datenbank für so große Datenmengen verwenden? Wenn nicht, kann ich mich an MySQL halten?
- Welche Datenbank soll ich verwenden?
- Sollte ich Datum und Uhrzeit in getrennten, indizierten (wenn möglich) Spalten aufbewahren, um die Daten für bestimmte Zeit- und Datumsperioden schnell abzurufen und zu verarbeiten, oder kann dies durch Aufbewahren des Zeitstempels in einer einzelnen Spalte erfolgen?
- Ist hier ein Zeitreihendatenmodellierungsansatz angebracht, und wenn nicht, können Sie mir Hinweise für ein gutes Tabellendesign geben?
Danke.
Antworten:
Dies ist genau das, was ich jeden Tag mache, außer dass ich anstelle der Stundendaten die 5-Minuten-Daten verwende. Ich lade jeden Tag ungefähr 200 Millionen Datensätze herunter, daher ist die Menge, über die Sie hier sprechen, kein Problem. Die 5-Minuten-Daten sind ungefähr 2 TB groß und ich habe Wetterdaten, die 50 Jahre zurückliegen, auf Stundenbasis nach Standort. Lassen Sie mich Ihre Fragen beantworten, basierend auf meinen Erfahrungen:
Allgemeiner Tipp: Ich speichere die meisten Daten zwischen zwei Datenbanken, die erste sind reine Zeitreihendaten und normalisiert. Meine zweite Datenbank ist sehr de-normalisiert und enthält voraggregierte Daten. So schnell mein System ist, ich bin nicht blind für die Tatsache, dass Benutzer nicht einmal 30 Sekunden auf das Laden eines Berichts warten möchten - auch wenn ich persönlich der Meinung bin, dass 30 Sekunden zum Knacken von 2 TB Daten extrem schnell sind.
Um zu erläutern, warum ich empfehle, die Stunde getrennt vom Datum zu speichern, hier ein paar Gründe, warum ich das so mache:
DATETIME
Säule.Wie ich oben sagte, basiert dies alles auf meiner persönlichen Erfahrung, und lassen Sie mich Ihnen sagen, es waren einige harte Jahre und eine Menge Umgestaltungen, um dahin zu gelangen, wo ich jetzt bin. Tun Sie nicht das, was ich getan habe, lernen Sie aus meinen Fehlern und stellen Sie sicher, dass Sie die Endbenutzer Ihres Systems (oder Entwickler, Berichtsautoren usw.) in die Entscheidungen über Ihre Datenbank einbeziehen.
quelle
PostgreSQL- und BRIN-Indizes
Testen Sie es selbst. Dies ist kein Problem auf einem 5 Jahre alten Laptop mit einer SSD.
So dauerte es 22 Minuten, um die Tabelle zu erstellen. Vor allem, weil der Tisch bescheidene 97GB hat. Als nächstes erstellen wir die Indizes,
Die Erstellung der Indizes dauerte ebenfalls sehr lange. Weil sie BRIN sind, sind sie nur 2-3 MB groß und können problemlos im RAM gespeichert werden. Das Lesen von 96 GB erfolgt nicht sofort, ist jedoch für meinen Laptop bei Ihrer Arbeitsbelastung kein wirkliches Problem.
Jetzt fragen wir es ab.
Update mit Zeitstempeln
Hier generieren wir eine Tabelle mit verschiedenen Zeitstempeln, um die Anforderung zum Indexieren und Durchsuchen einer Zeitstempelspalte zu erfüllen. Die Erstellung dauert etwas länger, da sie
to_timestamp(int)
wesentlich langsamer ist alsnow()
(was für die Transaktion zwischengespeichert wird).Jetzt können wir stattdessen eine Abfrage für einen Zeitstempelwert ausführen.
Ergebnis:
So können wir in 83.321 ms 86.401 Datensätze in einer Tabelle mit 1,7 Milliarden Zeilen zusammenfassen. Das sollte vernünftig sein.
Stundenende
Die Berechnung des Stundenendes ist ebenfalls recht einfach. Schneiden Sie die Zeitstempel ab und fügen Sie dann einfach eine Stunde hinzu.
Es ist wichtig zu beachten, dass kein Index für die Aggregation verwendet wird, obwohl dies möglich ist. Wenn das Ihre typische Abfrage ist, möchten Sie wahrscheinlich einen BRIN
date_trunc('hour', tsin)
darin haben, ein kleines Problem,date_trunc
das nicht unveränderlich ist, also müssen Sie es zuerst umbrechen, um es so zu machen.Partitionierung
Ein weiterer wichtiger Punkt in Bezug auf PostgreSQL ist, dass PG 10 Partitionierungs-DDL bringt . So können Sie beispielsweise problemlos Partitionen für jedes Jahr erstellen. Unterteilen Sie Ihre bescheidene Datenbank in kleine Datenbanken. Dabei sollten Sie in der Lage sein, Btree-Indizes anstelle von BRIN zu verwenden und zu verwalten, was sogar noch schneller wäre.
Oder Wasauchimmer.
quelle
Es wundert mich, dass hier niemand das Benchmarking erwähnt hat - bis @EvanCarroll mit seinem hervorragenden Beitrag daherkam!
Wenn ich Sie wäre, würde ich einige Zeit (und ja, ich weiß, es ist ein kostbares Gut!) Damit verbringen, Systeme einzurichten und das auszuführen, was Sie denken (hier können Sie Eingaben von Endbenutzern machen!), Sagen wir, Ihre 10 häufigsten Anfragen.
Meine eigenen Gedanken:
NoSQL-Lösungen können für bestimmte Anwendungsfälle sehr gut funktionieren, sind jedoch häufig für Ad-hoc-Abfragen unflexibel. Eine amüsante Darstellung von NoSQL durch Brian Aker - ehemaliger Chefarchitekt von MySQL - finden Sie hier !
Ich stimme @ Mr.Brownstone zu, dass Ihre Daten hervorragend für eine relationale Lösung geeignet sind (und diese Meinung wurde von Evan Carroll bestätigt )!
Wenn ich mich auf irgendwelche Ausgaben festlegen würde, dann auf meine Festplattentechnologie! Ich würde jedes Geld, das mir zur Verfügung steht, für NAS oder SAN oder für einige SSD-Festplatten ausgeben, um meine selten geschriebenen aggregierten Daten zu speichern!
Zuerst würde ich schauen, was ich zur Verfügung habe jetzt . Führen Sie einige Tests durch und zeigen Sie den Entscheidungsträgern die Ergebnisse. Sie haben bereits einen Vertreter in Form der Arbeit von EC ! Aber ein oder zwei schnelle Tests, die auf Ihrer eigenen Hardware durchgeführt wurden, wären überzeugender!
Dann denken Sie an Geld ausgeben! Wenn Sie Geld ausgeben möchten, sollten Sie sich zuerst die Hardware und nicht die Software ansehen. AFAIK, Sie können die Festplattentechnologie für einen Testzeitraum ausleihen oder, noch besser, ein paar Proof-of-Concept-Tests in der Cloud durchführen.
Meine persönliche erste Anlaufstelle für ein Projekt wie dieses wäre PostgreSQL. Das heißt nicht, dass ich eine proprietäre Lösung ausschließen würde, aber die Gesetze der Physik und der Festplatten sind für alle gleich! "Yae cannae beet die Gesetze der Physik Jim" :-)
quelle
Wenn Sie dies noch nicht getan haben, schauen Sie sich ein Zeitreihen-DBMS an, da es für das Speichern und Abfragen von Daten optimiert ist, bei denen der primäre Fokus auf dem Datums- / Zeit-Typ liegt. In der Regel werden Zeitreihendatenbanken zum Aufzeichnen von Daten im Minuten- / Sekunden- / Subsekundenbereich verwendet. Daher bin ich mir nicht sicher, ob sie für stündliche Inkremente geeignet sind. Allerdings scheint diese Art von DBMS einen Blick wert zu sein. Derzeit scheint InfluxDB die etablierteste und am weitesten verbreitete Zeitreihendatenbank zu sein.
quelle
Natürlich ist dies kein NoSQL-Problem, aber ich würde vorschlagen, dass eine RDBMS-Lösung zwar funktioniert, ein OLAP-Ansatz jedoch besser geeignet ist. Angesichts der sehr begrenzten Datenbereiche empfehle ich dringend, die Verwendung einer spaltenbasierten Datenbank zu untersuchen lieber als zeilenbasiert. Stellen Sie sich das so vor, Sie haben vielleicht 1,7 Milliarden Daten, aber Sie brauchen immer noch nur 5 Bits, um jeden möglichen Wert von Stunde oder Tag des Monats zu indizieren.
Ich habe Erfahrung mit einer ähnlichen Problemdomäne, in der Sybase IQ (jetzt SAP IQ) verwendet wird, um bis zu 300 Millionen Zähler pro Stunde mit Leistungsdaten für Telekommunikationsgeräte zu speichern. Ich bezweifle jedoch, dass Sie das Budget für eine solche Lösung haben. In der Open-Source-Arena ist MariaDB ColumnStore ein vielversprechender Kandidat, aber ich würde auch empfehlen, MonetDB zu untersuchen.
Da die Abfrageleistung ein wichtiger Treiber für Sie ist, sollten Sie überlegen, wie Abfragen formuliert werden. Hier zeigen OLAP und RDBMS die größten Unterschiede: - Mit OLAP normalisieren Sie die Abfrageleistung, nicht die Wiederholung, den Speicherbedarf oder sogar die Konsistenz. Zusätzlich zum ursprünglichen Zeitstempel (Sie haben sich hoffentlich daran erinnert, die Zeitzone zu erfassen?) Gibt es ein separates Feld für den UTC-Zeitstempel, weitere Felder für Datum und Uhrzeit sowie weitere Felder für Jahr, Monat, Tag, Stunde und Minute und UTC-Offset. Wenn Sie zusätzliche Informationen zu Standorten haben, können Sie diese in einer separaten Standorttabelle aufbewahren, die bei Bedarf nachgeschlagen werden kann. Sie können den Schlüssel zu dieser Tabelle in Ihrem Hauptdatensatz beibehalten, aber den vollständigen Standortnamen in Ihrer Haupttabelle beibehalten na ja, immerhin
Verwenden Sie abschließend separate Tabellen für häufig verwendete aggregierte Daten und füllen Sie diese mithilfe von Stapeljobs auf. Auf diese Weise müssen Sie die Übung nicht für jeden Bericht wiederholen, der einen aggregierten Wert verwendet und Abfragen vornimmt, die den aktuellen Wert mit dem historischen Wert oder dem aktuellen Wert vergleichen historisch zu historisch viel einfacher und viel, viel schneller.
quelle