Möglichkeit zur Neugestaltung der Datenbank: Welches Tabellendesign soll für diese Sensordatensammlung verwendet werden?

13

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 dataTabelle trotz aktivierter Indizes idund so viele Zeilen enthält (~ 10 Millionen), data_timestampist 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.

JYelton
quelle
Damit diese Frage die richtige Antwort erhält , sollten Sie wahrscheinlich erweitern, wie die Daten tatsächlich verwendet werden. In Bezug auf die Tiefe der Informationen, die Sie bisher angegeben haben, sind Sie der Kurve voraus, aber Sie stellen Ihre Frage möglicherweise aus einem falschen Blickwinkel.
Mark Storey-Smith
Guter Punkt, @Mark, ich werde auch darauf eingehen. Ich habe versucht, keine zu lange Frage zu haben, aus Angst, sie würde überwältigen.
JYelton

Antworten:

5

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:

Die Partitionierung von Daten sollte dazu dienen, Daten zu gruppieren, die logisch und zusammenhängend derselben Klasse angehören. Die Leistung beim Durchsuchen jeder Partition muss nicht der Hauptaspekt sein, solange die Daten korrekt gruppiert sind. Wenn Sie die logische Partitionierung erreicht haben, konzentrieren Sie sich auf die Suchzeit. Wenn Sie Daten nur durch ID trennen, ist es möglich, dass auf viele Datenzeilen nie zum Lesen oder Schreiben zugegriffen wird. Nun sollte dies eine wichtige Überlegung sein: Suchen Sie alle IDs, auf die am häufigsten zugegriffen wird, und partitionieren Sie sie danach. Alle IDs, auf die weniger häufig zugegriffen wird, sollten sich in einer großen Archivtabelle befinden, auf die durch Indexsuche für diese Abfrage "Einmal im blauen Mond" weiterhin zugegriffen werden kann.

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 TABLEder 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

  1. Aus Ihrem Kommentar geht hervor, dass Sie möglicherweise eine Normalisierung benötigen.
  2. Möglicherweise müssen Sie alles, was älter als 90 Tage ist, in eine Archivtabelle migrieren, aber gleichzeitig auf das Archiv und das Arbeitsset zugreifen. Wenn es sich bei Ihren Daten ausschließlich um MyISAM handelt, empfehle ich die Verwendung der MERGE-Speicher-Engine. Zunächst erstellen Sie die MERGE-Tabellenzuordnung, die eine funktionierende MyISAM-Tabelle und eine archivierte MyISAM-Tabelle vereint. Sie würden Daten in einer MyISAM-Tabelle für weniger als 91 Tage aufbewahren und alle Daten, die älter als 90 Tage sind, in das Archiv verschieben. Sie würden nur die MERGE-Tabellenzuordnung abfragen.

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

RolandoMySQLDBA
quelle
Es gibt Spalten, die weniger häufig benötigt werden, aber alle Sensoren erhalten ungefähr den gleichen Prozentsatz an Aufmerksamkeit. Daher kann ich mir vorstellen, dass eine vertikale Aufteilung des Tisches vorteilhaft wäre. Zum Beispiel eine Tabelle mit 20 Spalten (auf die häufig zugegriffen wird) und eine Tabelle mit 80 Spalten (auf die selten zugegriffen wird). Ich bin mir nicht sicher, ob das dasselbe ist wie Partitionieren.
JYelton,
Danke für die Bearbeitung. Ich habe Ihren Beitrag über "Zu viele Spalten in MySQL" gelesen. Ich werde meine Frage mit einigen zusätzlichen Punkten bearbeiten, die nützlich sein können.
JYelton
5

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.

FrustratedWithFormsDesigner
quelle
Eine Aufbewahrung über 90 Tage hinaus ist an dieser Stelle nicht erforderlich, aber wünschenswert. Ich bin damit einverstanden, dass es am besten ist, in einer "Archiv" -Tabelle zu speichern. Grafiken und Datenanalysen reichen von wenigen Stunden bis zu 90 Tagen. Die meisten Grafikanforderungen verwenden nur die Daten der letzten Woche oder so, aber 90-Tage-Grafiken sind üblich. Unsere Firma hat (noch) keine längeren Berichte angefordert.
JYelton,
@JYelton: Sie können so viele Ebenen in diesem Ansatz haben, wie Sie möchten. Die aktuellste Tabelle könnte nur von Heute sein. Der nächste Tisch könnte von heute bis vor 2 Wochen sein. Der nächste Tisch könnte von Heute bis vor 90 Tagen liegen. Der letzte Tisch könnte ALLES.
FrustratedWithFormsDesigner
Wenn ich Sie richtig verstehe, möchten Sie die Tabelle replizieren, jedoch mit unterschiedlichen Zeiträumen. Wenn also jemand einen 7-Tage-Bericht anfordert, wird eine Tabelle verwendet, die nur eine Woche zurückliegt. Wenn sie dann auf 8 Tage erweitert werden, wird die nächstgrößere Tabelle (z. B. 30 Tage) verwendet. Dies würde mit Sicherheit die Geschwindigkeit von Abfragen mit kürzerer Dauer verbessern, jedoch zu einem (billigen) Preis für Speicherplatz und Programmierlogik, um mit den gestuften Tabellen umzugehen (nicht so billig).
JYelton
@JYelton: Ja, ich denke du verstehst es richtig. Wenn die Abfragezeitraumbereiche Standard sind (heute - 1 Tag, heute - 7 Tage, heute - 30 Tage, heute - 90 Tage), wird es meiner Meinung nach nicht allzu schwierig, da Sie immer wissen, zu welcher Tabelle Sie gehören schlagen. Wenn die Zeitbereiche unterschiedlich lang sein können und der Beginn des Bereichs möglicherweise nicht das aktuelle Datum ist, ist die zu implementierende Logik korrekt und Abfragen, die tabellenübergreifend ausgeführt werden, können mit UNION-Operationen für mehrere Tabellen teuer werden.
FrustratedWithFormsDesigner