Hintergrund
Ich habe ein Netzwerk von ungefähr 2000 Sensoren, von denen jeder ungefähr 100 Datenpunkte hat, die wir in 10-Minuten-Intervallen sammeln. Bei diesen Datenpunkten handelt es sich normalerweise um int-Werte, bei einigen handelt es sich jedoch um Zeichenfolgen und Gleitkommazahlen. Diese Daten sollten 90 Tage gespeichert werden, wenn möglich und dennoch effizienter.
Datenbank Design
Als ich ursprünglich mit diesem Projekt beauftragt war, habe ich eine C # -App geschrieben, die kommagetrennte Dateien für jeden Sensor schrieb. Zu der Zeit gab es nicht so viele, als jemand Trends betrachten wollte, öffneten wir die CSV in Excel und zeichneten sie nach Bedarf.
Die Dinge wuchsen und wir wechselten zu einer MySQL-Datenbank. Ich habe für jeden Sensor eine Tabelle erstellt (ja, ich weiß, viele Tabellen!); Es hat gut funktioniert, aber es hat einige Einschränkungen. Bei so vielen Tabellen ist es offensichtlich unmöglich, eine Abfrage zu schreiben, die bei der Suche nach einem bestimmten Wert Daten zwischen allen Sensoren findet.
Für die nächste Version habe ich zu Microsoft SQL Server Express gewechselt und alle Sensordaten in einer großen Tabelle zusammengefasst. Dies funktioniert auch und lässt uns Abfragen durchführen, um Werte unter allen Sensoren zu finden, die von Interesse sind. Ich bin jedoch auf das 10-GB-Limit für die Express-Version gestoßen und habe beschlossen, wieder auf MySQL umzustellen, anstatt in SQL Server Standard zu investieren.
Die Frage
Ich bin mit der Leistung und Skalierbarkeit von MySQL zufrieden, bin mir aber nicht sicher, ob es am besten ist, sich an den All-Data-in-One-Table-Ansatz zu halten. 10 GB in einer einzelnen Tabelle scheinen nach einem anderen Design zu verlangen. Ich sollte erwähnen, dass die Notwendigkeit, Daten für die grafische Darstellung abzufragen, weiterhin besteht, und ich bin besorgt, dass es Leistungsprobleme bei einer Abfrage gibt, die beispielsweise Temperaturdaten für einen Sensor über die gesamten 90 Tage grafisch darstellt. (Mit anderen Worten, das Diagramm sollte schnell erstellt werden können, ohne darauf zu warten, dass SQL die Datenstapel sortiert, um den interessierenden Sensor zu isolieren.)
Sollte ich diese Tabelle in irgendeiner Weise aufteilen, um die Leistung zu steigern? Oder ist es nicht ungewöhnlich, einen so großen Tisch zu haben?
Ich habe Indizes für die Sensor-ID- und Zeitstempel-Spalten, die so ziemlich die definierenden Grenzen für jede Abfrage darstellen. (dh Daten für Sensor X von Zeitpunkt A zu Zeitpunkt B abrufen).
Ich habe ein wenig über Sharding und Partitioning gelesen, halte diese in diesem Fall jedoch nicht für angemessen.
Bearbeiten:
Aufgrund der bisherigen Kommentare und Antworten können einige zusätzliche Informationen hilfreich sein:
Nicht unbefristete Speicherung: Derzeit speichere ich keine Daten seit 90 Tagen. Täglich führe ich eine Abfrage aus, mit der Daten entfernt werden, die älter als 90 Tage sind. Wenn es in Zukunft wichtig wird, werde ich mehr speichern, aber es ist vorerst ausreichend. Dies hilft, die Größe in Schach zu halten und die Leistung hoch zu halten.
Motortyp: Die ursprüngliche MySQL-Implementierung verwendete MyISAM. Wenn die Tabellen dieses Mal für die neue Implementierung erstellt werden (eine Datentabelle anstelle von vielen), wird standardmäßig InnoDB verwendet. Ich glaube nicht, dass ich eine Anforderung für das eine oder andere habe.
Normalisierung: Neben der Datenerfassungstabelle gibt es natürlich noch weitere Tabellen. In diesen Support-Tabellen werden beispielsweise Netzwerkinformationen für die Sensoren, Anmeldeinformationen für Benutzer usw. gespeichert. Es gibt nicht viel zu normalisieren (soweit ich weiß). Der Grund, warum die Datentabelle so viele Spalten enthält, ist, dass von jedem Sensor so viele Variablen vorhanden sind. (Mehrere Temperaturen, Lichtverhältnisse, Luftdruck usw.) Normalisierung bedeutet für mich, dass es keine redundanten Daten oder sich wiederholenden Gruppen gibt. (Zumindest für 1NF.) Für einen bestimmten Sensor sind zum Speichern aller Werte zu einem bestimmten Zeitpunkt nur eine Datenzeile und keine 1: N-Beziehungen erforderlich (wie ich sehe).
Ich könnte die Tabelle funktional aufteilen und beispielsweise alle temperaturbezogenen Werte in einer Tabelle und alle luftdruckbezogenen Werte in einer anderen Tabelle angeben. Während dies die Effizienz für jemanden verbessern kann, der eine reine Temperaturabfrage durchführt, muss ich dennoch alle Daten auf einmal einfügen. Dennoch könnte sich der Effizienzgewinn für SELECT-Operationen lohnen. Offensichtlich ist es besser, die Tabelle vertikal aufzuteilen, je nachdem, wie oft Benutzer die Daten anfordern. Vielleicht ist das alles, was ich tun sollte. Wenn ich meine Frage stelle, suche ich vermutlich nach einer Bestätigung, dass es sich lohnt, dies zu tun.
Bearbeiten 2:
Datennutzung : Letztendlich wird ein Großteil der Daten nie angezeigt oder benötigt, da wir uns in der Regel nur auf problematische Elemente konzentrieren. Bei der Suche nach Problemen verwenden wir jedoch verschiedene Tools, um die Daten zu durchsuchen und zu bestimmen, welche Elemente vergrößert werden sollen.
Zum Beispiel haben wir eine Korrelation zwischen einem Wert für die Speichernutzung (ein kundenspezifisches proprietäres Softwareprogramm) und einem Neustart / Absturz festgestellt. Einer der Datenpunkte, die ich sammle, bezieht sich auf diese Speichernutzung, und ich konnte mir historische Daten ansehen, um zu zeigen, dass Geräte nach Überschreiten einer bestimmten Speichernutzung instabil werden. Für die Untergruppe der Geräte, auf denen diese Software ausgeführt wird, überprüfe ich heute diesen Wert und gebe einen Neustartbefehl aus, wenn er zu hoch ist. Bis dies entdeckt wurde, dachte ich nicht, dass das Sammeln dieser Daten von Wert ist.
Aus diesem Grund habe ich behauptet, dass die rund 100 Datenpunkte gesammelt und gespeichert werden, auch wenn der Wert fraglich ist. Im normalen Alltag untersuchen Benutzer jedoch in der Regel ein Dutzend dieser Parameter. Wenn sich ein Benutzer für ein bestimmtes geografisches Gebiet interessiert, kann er (mithilfe von Software) Diagramme oder Tabellen mit Daten für möglicherweise ein paar Dutzend Sensoren erstellen. Es ist nicht ungewöhnlich, ein 30-Tage-Diagramm mit zwei oder drei Plotlinien zu betrachten, die beispielsweise Temperatur, Luftdruck und Lichtwerte anzeigen. Wenn Sie dies tun, wird eine Abfrage ähnlich der folgenden ausgeführt:
SELECT sensor_id, location, data_timestamp, temp1, air1, light1
FROM data
WHERE data_timestamp >= '2012-02-01'
AND sensor_id IN (1, 2, 3);
(In der ursprünglichen MySQL-Version, in der jeder Sensor eine eigene Tabelle hatte, wurden drei separate Abfragen ausgegeben, die Ergebnisse wurden jedoch in Software kombiniert, um das Diagramm zu erstellen.)
Da die data
Tabelle trotz aktivierter Indizes id
und so viele Zeilen enthält (~ 10 Millionen), data_timestamp
ist die Leistung erheblich schlechter als im Szenario mit mehreren Tabellen (4500 Zeilen wurden in 9 Sekunden zurückgegeben, im Gegensatz zu weniger als einer Sekunde in diesem Beispiel). Die Fähigkeit zu finden, welche Sensoren bestimmte Kriterien erfüllen, ist im Mehrtabellenschema praktisch Null und daher der Grund für den Wechsel zu einer einzelnen Tabelle.
Diese Art der Abfrage kann von mehreren Benutzern schnell hintereinander durchgeführt werden, da sie verschiedene Datengruppen auswählen und die Diagramme der einzelnen Ergebnisse vergleichen. Es kann ziemlich frustrierend sein, fast 10 Sekunden pro Grafik oder Tabelle zu warten.
Daten werden nach 90 Tagen verworfen. Es könnte archiviert werden, ist aber derzeit nicht erforderlich.
Hoffentlich können Sie anhand dieser Informationen besser erkennen, wie die Daten nach der Erfassung und Speicherung verwendet werden.
quelle
Antworten:
Sie sollten überlegen, die Tabelle aus einem wichtigen Grund zu partitionieren.
Alle Indizes, die Sie für eine riesige Tabelle haben, selbst ein einziger Index, kann eine Menge CPU-Last und Festplatten-E / A generieren, nur um die Indexwartung beim Ausführen von INSERTs, UPDATEs und DELETEs durchzuführen.
Ich schrieb am 7. Oktober 2011 einen früheren Beitrag darüber, warum das Partitionieren von Tabellen eine große Hilfe sein würde. Hier ist ein Auszug aus meinem letzten Beitrag:
Sie können meinen gesamten Beitrag später lesen .
Um auf den Punkt zu kommen, müssen Sie herausfinden, welche Daten in Ihrer 10-GB-Tabelle selten verwendet werden. Diese Daten sollten in einer Archivtabelle abgelegt werden, auf die zugegriffen werden kann, wenn Sie Ad-hoc-Abfragen für historische Daten benötigen. Das Migrieren dieses Archivs von den 10 GB, gefolgt von
OPTIMIZE TABLE
der 10 GB-Tabelle, kann zu einem Arbeitssatz führen, mit dem SELECTs, INSERTs, UPDATEs und DELETEs schneller ausgeführt werden können. Sogar DDL würde mit einem 2-GB-Arbeitsspeicher schneller als mit einem 10-GB-Tisch.UPDATE 2012-02-24 16:19 EDT
Zwei Punkte zu beachten
Hier sind zwei Beiträge, die ich gemacht habe, wie man es benutzt:
Hier ist ein zusätzlicher Beitrag, den ich auf Tabellen mit vielen Spalten geschrieben habe
Zu viele Spalten in MySQL
quelle
Interessant ... Wenn alle Sensoren die gleiche Art von Daten liefern, ist es sinnvoll, sie alle in dieselbe Tabelle zu schreiben, aber mit dieser Datenmenge kann ich sehen, warum Sie sich Sorgen um die Leistung machen.
Sind 90 Tage die übliche Zeit, für die Sie ein Diagramm erstellen? In diesem Fall könnten Sie zwei Tabellen haben: Die Hauptsensordatentabelle, in der Daten von 90 Tagen bis heute (oder ein bisschen mehr, wenn Sie eine Pause einlegen möchten) gespeichert sind, und alles, was älter ist, wird in der Archivtabelle gespeichert. Dies könnte dazu beitragen, die Größe der Tabelle zu verringern, aus der Berichte generiert werden. Hoffentlich befindet sich der Großteil Ihrer 10 GB Daten in der Archivtabelle und nicht in der Haupttabelle. Der Archivierungsjob kann für die nächtliche Ausführung eingeplant werden.
Ziehen Sie möglicherweise auch die Erstellung einer separaten Berichtsdatenbank in Betracht, in der die Daten in einer Struktur gespeichert werden, die sich besser zum Generieren von Berichten eignet (Tabellen, die so gestaltet sind, dass sie besser mit den abgefragten Werten übereinstimmen, und vorab berechnete und aggregierte Werte, die andernfalls viel Zeit in Anspruch nehmen würden Wenn möglich, generieren Sie sie und füllen Sie sie regelmäßig (z. B. nachts) aus der Hauptdatenbank neu auf. Wenn Sie Berichte benötigen, die aus aktuellen Daten erstellt wurden, funktioniert dies möglicherweise nicht so gut.
quelle