Kann MySQL Abfragen in Milliarden von Zeilen sinnvoll ausführen?


283

Ich plane, Scans von einem Massenspektrometer in einer MySQL-Datenbank zu speichern und möchte wissen, ob das Speichern und Analysieren dieser Datenmenge aus der Ferne möglich ist. Ich weiß, dass die Leistung je nach Umgebung sehr unterschiedlich ist, aber ich suche nach der ungefähren Größenordnung: Dauern Abfragen 5 Tage oder 5 Millisekunden?

Eingabeformat

Jede Eingabedatei enthält einen einzelnen Lauf des Spektrometers. Jeder Lauf besteht aus einer Reihe von Scans, und jeder Scan enthält eine geordnete Reihe von Datenpunkten. Es gibt einige Metadaten, aber der größte Teil der Datei besteht aus 32- oder 64-Bit-Arrays (Ints oder Floats).

Host-System

| ---------------- + ------------------------------- |
| OS | Windows 2008 64-Bit |
| MySQL-Version | 5.5.24 (x86_64) |
| CPU | 2x Xeon E5420 (insgesamt 8 Kerne) |
| RAM | 8 GB |
| SSD-Dateisystem | 500 GiB |
| HDD RAID | 12 TiB |
| ---------------- + ------------------------------- |

Auf dem Server werden einige andere Dienste ausgeführt, deren Prozessorzeit vernachlässigbar ist.

Dateistatistik

| ------------------ + -------------- |
| Anzahl der Dateien | ~ 16.000 |
| Gesamtgröße | 1,3 TiB |
| Mindestgröße | 0 Bytes |
| max größe | 12 GiB |
| meine | 800 MiB |
| Median | 500 MiB |
| Gesamtdatenpunkte | ~ 200 Milliarden |
| ------------------ + -------------- |

Die Gesamtzahl der Datenpunkte ist eine sehr grobe Schätzung.

Vorgeschlagenes Schema

Ich habe vor, die Dinge "richtig" zu machen (dh die Daten wie verrückt zu normalisieren) und hätte dann eine runsTabelle, eine spectraTabelle mit einem Fremdschlüssel für runsund eine datapointsTabelle mit einem Fremdschlüssel für spectra.

Die 200-Milliarden-Datenpunkt-Frage

Ich werde mehrere Spektren und möglicherweise sogar mehrere Läufe analysieren, was zu Abfragen führt, die Millionen von Zeilen berühren könnten. Angenommen, ich indiziere alles richtig (was ein Thema für eine andere Frage ist) und versuche nicht, Hunderte von MiB über das Netzwerk zu mischen, ist es für MySQL aus der Ferne plausibel, damit umzugehen?

zusätzliche Information

Die Scandaten stammen aus Dateien im XML-basierten mzML- Format. Das Fleisch dieses Formats befindet sich in den <binaryDataArrayList>Elementen, in denen die Daten gespeichert sind. Jeder Scan erzeugt> = 2 <binaryDataArray>Elemente, die zusammen ein zweidimensionales (oder mehr) Array des Formulars bilden [[123.456, 234.567, ...], ...].

Diese Daten sind einmal beschreibbar, sodass die Aktualisierungsleistung und die Transaktionssicherheit keine Bedenken darstellen.

Mein naiver Plan für ein Datenbankschema lautet:

runs Tabelle

| Spaltenname | Typ |
| ------------- + ------------- |
| id | PRIMÄRSCHLÜSSEL |
| start_time | TIMESTAMP |
| name | VARCHAR |
| ------------- + ------------- |

spectra Tabelle

| Spaltenname | Typ |
| ---------------- + ------------- |
| id | PRIMÄRSCHLÜSSEL |
| name | VARCHAR |
| index | INT |
| spectrum_type | INT |
| Darstellung | INT |
| run_id | AUSLÄNDISCHER SCHLÜSSEL |
| ---------------- + ------------- |

datapoints Tabelle

| Spaltenname | Typ |
| ------------- + ------------- |
| id | PRIMÄRSCHLÜSSEL |
| spectrum_id | AUSLÄNDISCHER SCHLÜSSEL |
| mz | DOPPELT |
| num_counts | DOPPELT |
| index | INT |
| ------------- + ------------- |

Ist das vernünftig?


Wie Sie vielleicht schlussfolgern konnten, bin ich der Programmierer, nicht der Biologe im Labor, also kenne ich die Wissenschaft nicht annähernd so gut wie die tatsächlichen Wissenschaftler.

Hier ist eine Darstellung eines einzelnen Spektrums (Scan) der Art von Daten, mit denen ich mich befassen werde:

Viewer-Screenshot

Ziel der Software ist es herauszufinden, wo und wie bedeutend die Peaks sind. Wir verwenden ein proprietäres Softwarepaket, um dies herauszufinden, aber wir möchten unser eigenes Analyseprogramm (in R) schreiben, damit wir wissen, was zum Teufel unter den Laken vor sich geht. Wie Sie sehen, ist die überwiegende Mehrheit der Daten uninteressant, aber wir möchten keine potenziell nützlichen Daten löschen, die unser Algorithmus übersehen hat. Sobald wir eine Liste wahrscheinlicher Peaks haben, mit denen wir zufrieden sind, wird der Rest der Pipeline diese Peak-Liste anstelle der unformatierten Liste von Datenpunkten verwenden. Ich nehme an, dass es ausreichend wäre, die Rohdatenpunkte als großen Blob zu speichern, damit sie bei Bedarf erneut analysiert werden können, aber nur die Peaks als eindeutige Datenbankeinträge behalten. In diesem Fall würde es nur ein paar Dutzend Peaks pro Spektrum geben.



8
Da es sich um rohe A / D-Polling-Massenspektrometer-Daten handelt, erscheint es wirklich dumm, sie in der Datenbank zu speichern. Ich würde meine Rohdaten nehmen, sie sichern, verarbeiten und die verarbeiteten ERGEBNISSE in einer Datenbank speichern. Die Ergebnisse wären (a) Wellenformen, die eine Wellenform pro Zeile gespeichert haben, (b) andere Daten, die diesen Wellenformen zugeordnet sind, wie Kalibrierungskurven, und (c) Ergebniszeilen in der Datenbank. Dies würde Milliarden von Reihen von Blähungen von Ihrem Design abschneiden. Wenn Sie eine erste Analyse erneut ausführen möchten, müssen Sie einige Parameter bearbeiten, eine riesige Rechenoperation ausführen und die neuen Ergebnisse in der Datenbank speichern.
Warren P

Antworten:


115

Ich bin mit Ihren Anforderungen nicht sehr vertraut, aber vielleicht ist das Speichern jedes Datenpunkts in der Datenbank etwas übertrieben. Es klingt fast so, als würde man eine Bildbibliothek speichern, indem man jedes Pixel als separaten Datensatz in einer relationalen Datenbank speichert.

Das Speichern von Binärdaten in Datenbanken ist in der Regel die meiste Zeit falsch. Es gibt normalerweise einen besseren Weg, um das Problem zu lösen. Zwar ist das Speichern von Binärdaten in relationalen Datenbanken nicht von Natur aus falsch, doch überwiegen oftmals die Nachteile die Gewinne. Relationale Datenbanken eignen sich am besten zum Speichern relationaler Daten. Binärdaten sind nicht relational. Es vergrößert Datenbanken (häufig erheblich), kann die Leistung beeinträchtigen und zu Fragen bezüglich der Verwaltung von MySQL-Instanzen mit Milliarden Datensätzen führen. Die gute Nachricht ist, dass es Datenbanken gibt, die sich besonders gut zum Speichern von Binärdaten eignen. Eines davon ist Ihr Dateisystem, obwohl es nicht immer leicht zu erkennen ist! Überlegen Sie sich einfach eine Verzeichnis- und Dateinamenstruktur für Ihre Binärdateien.

Ein anderer Ansatz wäre die Verwendung eines dokumentbasierten Speichersystems für Ihre Datenpunkt- (und möglicherweise Spektren-) Daten und die Verwendung von MySQL für die Läufe (oder die Läufe möglicherweise in dieselbe Datenbank wie die anderen).


5
Warum wird das Speichern von Binärdaten in einer Datenbank als falsch angesehen? (Zum Teil, weil ich neugierig bin, aber auch, weil ich mir einen Anwendungsfall dafür

15
Wenn die Binärdaten einzeln keinen Wert haben, sollten sie nicht als eindeutige Zeile gespeichert werden. Pixel 500x325 auf einem Bild ist irrelevant.

1
Das ist ein sehr guter Punkt. Wir sollten die rohen Dateien wahrscheinlich behalten, falls wir später wieder etwas herausholen müssen, aber die Analogie zum Speichern von Bildern ist großartig. Wir werden niemals Zugriff auf jeden Datenpunkt benötigen (es sei denn, wir wiederholen die Peak-Extraktion), daher wäre es viel besser, die extrahierten statistischen Informationen einfach zu speichern.
Haxney

108

Ich habe einmal mit einer sehr großen (Terabyte +) MySQL-Datenbank gearbeitet. Der größte Tisch, den wir hatten, war buchstäblich mehr als eine Milliarde Zeilen. Dies war MySQL 5.0, daher ist es möglich, dass sich die Dinge verbessert haben.

Es funktionierte. MySQL hat die Daten die meiste Zeit korrekt verarbeitet. Es war jedoch äußerst unhandlich. (Wenn Sie eine Verfügbarkeit auf Six Sigma-Ebene mit einem Terabyte an Daten wünschen, verwenden Sie MySQL nicht. Wir waren ein Startup ohne DBA und mit begrenzten Mitteln.)

Das einfache Sichern und Speichern der Daten war eine Herausforderung. Es würde Tage dauern, um die Tabelle wiederherzustellen, wenn wir mussten.

Wir hatten zahlreiche Tabellen im Bereich von 10-100 Millionen Zeilen. Alle signifikanten Verknüpfungen mit den Tabellen waren zu zeitaufwändig und würden ewig dauern. Also haben wir gespeicherte Prozeduren geschrieben, um die Tabellen und Prozessverknüpfungen mit Bereichen von IDs zu vergleichen. Auf diese Weise würden wir die Daten 10-100.000 Zeilen gleichzeitig verarbeiten (Join gegen die IDs 1-100.000, dann 100.001-200.000 usw.). Dies war deutlich schneller als das Verbinden gegen den gesamten Tisch.

Die Verwendung von Indizes für sehr große Tabellen, die nicht auf dem Primärschlüssel basieren, ist ebenfalls sehr viel schwieriger. Mysql 5.0 speichert Indizes in zwei Teilen - es speichert Indizes (außer dem Primärindex) als Indizes für die Primärschlüsselwerte. Indizierte Suchvorgänge werden also in zwei Teilen durchgeführt: Zuerst ruft MySQL einen Index auf und entnimmt ihm die zu suchenden Primärschlüsselwerte. Anschließend wird der Primärschlüsselindex erneut durchsucht, um herauszufinden, wo sich diese Werte befinden.

Dies hat zur Folge, dass bei sehr großen Tabellen (1-200 Millionen plus Zeilen) die Indizierung für Tabellen restriktiver ist. Sie benötigen weniger, einfachere Indizes. Und selbst einfache select-Anweisungen, die sich nicht direkt auf einem Index befinden, werden möglicherweise nie wieder verwendet. Wo Klauseln Indizes treffen oder vergessen müssen .

Trotzdem funktionierten die Dinge tatsächlich. Wir konnten MySQL mit diesen sehr großen Tabellen verwenden, Berechnungen durchführen und die richtigen Antworten erhalten.

Der Versuch, eine Analyse von 200 Milliarden Datenzeilen durchzuführen, würde sehr hochwertige Hardware und viel Handarbeit und Geduld erfordern. Nur die Daten in einem Format zu sichern, aus dem Sie sie wiederherstellen können, wäre ein bedeutender Job.

Ich stimme der Antwort von srini.venigalla zu, dass die Normalisierung der Daten wie verrückt hier möglicherweise keine gute Idee ist. Wenn Sie Verknüpfungen über mehrere Tabellen mit so vielen Daten ausführen, besteht das Risiko, dass Dateien sortiert werden. Dies kann dazu führen, dass einige Ihrer Abfragen einfach nie mehr zurückkehren. Das Denormallisieren mit einfachen, ganzzahligen Schlüsseln bietet Ihnen bessere Erfolgschancen.

Alles, was wir hatten, war InnoDB. In Bezug auf MyISAM vs. InnoDB: Die Hauptsache wäre, die beiden nicht zu mischen. Sie können einen Server nicht wirklich für beide optimieren, da MySQL Schlüssel und andere Daten zwischenspeichert. Wählen Sie das eine oder das andere für alle Tabellen auf einem Server aus, wenn Sie können. MyISAM kann bei einigen Geschwindigkeitsproblemen hilfreich sein, aber möglicherweise nicht bei der gesamten DBA-Arbeit, die erledigt werden muss - was ein Mörder sein kann.


1
MySQL hat sich in der Indexabteilung seit 5.0 stark verbessert. Es wäre interessant zu sehen, wie es sich jetzt verhält.
Ring Ø

70

Normalisierung der Daten wie verrückt

In diesem Fall ist es möglicherweise nicht die richtige Strategie, die Daten wie verrückt zu normalisieren. Lassen Sie Ihre Optionen offen, indem Sie die Daten sowohl in normalisierter Form als auch in Form von materialisierten Ansichten speichern, die für Ihre Anwendung besonders geeignet sind. Der Schlüssel für diese Art von Anwendungen ist NICHT das Schreiben von Ad-hoc-Abfragen. Die Abfragemodellierung ist wichtiger als die Datenmodellierung. Beginnen Sie mit Ihren Zielabfragen und arbeiten Sie auf das optimale Datenmodell hin.

Is this reasonable?

Ich würde auch eine zusätzliche flache Tabelle mit allen Daten erstellen.

run_id | spectrum_id | data_id | <data table columns..> |

Ich werde diese Tabelle als primäre Quelle für alle Abfragen verwenden. Der Grund ist, dass Sie keine Joins ausführen müssen. Verknüpfungen ohne Indizierung machen Ihr System sehr unbrauchbar, und Indizierungen für so große Dateien sind ebenso schrecklich.

Die Strategie ist, zuerst die obige Tabelle abzufragen, die Ergebnisse in eine temporäre Tabelle zu schreiben und die temporäre Tabelle mit den Nachschlagetabellen von Run und Spectrum zu verbinden, um die gewünschten Daten zu erhalten.


Haben Sie Ihren Schreibbedarf im Vergleich zum Lesebedarf analysiert? Es wird sehr verlockend sein, auf SQL zu verzichten und auf nicht standardmäßige Datenspeichermechanismen zurückzugreifen. Meiner Meinung nach sollte es der letzte Ausweg sein.

Um die Schreibgeschwindigkeit zu erhöhen, können Sie die Handler-Socket-Methode ausprobieren. Percona packt, wenn ich mich recht erinnere, Handler Socket in ihr Installationspaket. (keine Beziehung zu Percona!)

http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html


33

Die kurze Antwort ist ein qualifiziertes Ja - da die Anzahl der Zeilen zunimmt, gewinnen das genaue Schema, die Datentypen und die Operationen, die Sie auswählen, an Bedeutung.

Wie stark Sie Ihre Daten normalisieren, hängt von den Vorgängen ab, die Sie an den gespeicherten Daten ausführen möchten. Insbesondere Ihre 'Datenpunkt'-Tabelle scheint problematisch zu sein - planen Sie, den n-ten Punkt eines gegebenen Spektrums mit dem m-ten eines anderen zu vergleichen? Andernfalls kann die getrennte Aufbewahrung ein Fehler sein. Wenn Ihre Datenpunkte nicht für sich allein stehen, sondern nur im Kontext der zugehörigen Spektren sinnvoll sind, benötigen Sie keinen PRIMARY KEY - ein Fremdschlüssel für die Spektren und eine 'n-te' Spalte (Ihre 'Index'-Spalte?) Sind ausreichend .

Definieren Sie die Inter- und Intra-Spektrum-Operationen, die Sie ausführen müssen, und finden Sie dann den günstigsten Weg, um sie auszuführen. Wenn nur Gleichheit erforderlich ist, können sie denormalisiert werden - möglicherweise mit einigen vorberechneten statistischen Metadaten, die Ihre Operationen unterstützen. Wenn Sie unbedingt In-SQL-Zugriff auf einzelne Datenpunkte benötigen, reduzieren Sie die Größe jeder Zeile auf die minimale Anzahl von Feldern und den kleinstmöglichen Datentyp.

Das größte MySQL, das ich jemals persönlich verwaltet habe, war ~ 100 Millionen Zeilen. Bei dieser Größe möchten Sie Ihre Zeilen und damit Ihre Felder auf einer festen Größe halten - dies ermöglicht es MySQL, die Position einer beliebigen Zeile in der Tabelle effizient zu berechnen, indem Sie die feste Größe jeder Zeile multiplizieren (Zeigerarithmetik) Die genauen Details hängen davon ab, welche Speicher-Engine Sie verwenden möchten. Verwenden Sie MyISAM, wenn Sie damit durchkommen können, wenn es an Zuverlässigkeit mangelt, die es an Geschwindigkeit ausgleicht, und wenn es in Ihrer Situation ausreicht. Ersetzen Sie Felder mit variabler Größe wie VARCHAR durch CHAR (n) und verwenden Sie RTRIM () für Ihre Leseabfragen.

Sobald Ihre Tabellenzeilen eine feste Breite haben, können Sie die Anzahl der Bytes reduzieren, indem Sie die ganzzahligen Datentypen von MySQL (von denen einige nicht dem Standard entsprechen) sorgfältig auswerten . Jede 1-Byte-Einsparung, die Sie durch die Umwandlung eines 4-Byte-INT in ein 3-Byte-MEDIUMINT erzielen können, spart Ihnen ~ 1 MB pro Million Zeilen - was weniger Festplatten-E / A und effektiveres Caching bedeutet. Verwenden Sie die kleinstmöglichen Datentypen, mit denen Sie durchkommen können . Bewerten Sie die Gleitkommatypen sorgfältig und prüfen Sie, ob Sie 8-Byte-DOUBLE-Werte durch 4-Byte-FLOAT-Werte oder sogar <8-Byte- Festkommazahlen ersetzen können . Führen Sie Tests durch, um sicherzustellen, dass Sie später nicht beißen, was auch immer Sie auswählen.

Abhängig von den erwarteten Eigenschaften Ihres Datasets und den erforderlichen Vorgängen kann es zu weiteren Einsparungen bei ungewöhnlicheren Codierungen Ihrer Werte kommen (erwartete Muster / Wiederholungen, die als Index in eine Gruppe von Werten codiert werden können, Rohdaten, zu denen möglicherweise nur ein bedeutender Beitrag geleistet wird) Metadaten und verworfen werden, etc) - obwohl exotische, nicht intuitive, destruktive Optimierungen nur dann sinnvoll sind, wenn alle anderen Optionen ausprobiert wurden.

Ganz gleich, was Sie letztendlich tun, gehen Sie nicht davon aus, dass Sie das perfekte Schema ausgewählt haben, und geben Sie dann blind 10 Millionen Datensätze aus. Gute Designs brauchen Zeit, um sich weiterzuentwickeln. Erstellen Sie einen großen, aber überschaubaren Satz von Testdaten (z. B. 1 bis 5%), und überprüfen Sie die Richtigkeit und Leistung Ihres Schemas. Sehen Sie sich an, wie verschiedene Vorgänge ausgeführt werden (http://dev.mysql.com/doc/refman/5.0/en/using-explain.html), und stellen Sie sicher, dass Sie Ihr Schema so ausbalancieren, dass die häufigsten Vorgänge bevorzugt werden.

Habe ich kurz gesagt? Hoppla. Trotzdem viel Glück!


23

Es scheint, dass der einzige Grund, die Datenpunktdaten aus dem XML (im Gegensatz zu den Metadaten wie Zeitpunkt und Art der Ausführung) in ein Datenbankformular zu schreddern, darin besteht, dass Sie die Spektren über Arrays hinweg analysieren - dh möglicherweise alle finden läuft mit einer bestimmten Signatur. Nur Sie kennen Ihre Problemdomäne im Moment, aber dies könnte mit dem Speichern von Musik mit 96 kHz und 1 Sample pro Zeile vergleichbar sein. Ich bin nicht sicher, ob es mehr um die Größe geht als um die Verwendung der Daten. Das Abfragen der Daten entspricht dem Abfragen der relativen Amplitude in 2 Minuten für alle Songs von The Beatles. Wenn Sie die Art der Analysen kennen, die durchgeführt werden können, ist es durchaus möglich, dass die Durchführung dieser Analysen an den Signalen und die Speicherung dieser Analysen in den Metadaten über den Lauf sinnvoller ist.

Ich bin mir auch nicht sicher, ob Ihre Quelldaten spärlich sind. Es ist durchaus möglich, dass ein Spektrum in der Datenbank nur Einträge ungleich Null enthält, während das ursprüngliche XML Einträge ungleich Null enthält, sodass die Gesamtanzahl der Zeilen möglicherweise viel geringer ist als in den Quelldaten.

Wie bei vielen Fragen ist es wahrscheinlich sinnvoller, sich vor dem Umgang mit MySQL mit Ihrem Modell einen Schritt zurück zu machen, sich das Modell anzusehen und zu sehen, wie es verwendet werden soll, als sich nur um die Leistung zu sorgen.


Nach Durchsicht Ihrer Fragenaktualisierungen denke ich, dass ein Modell, in dem die Binärdaten als BLOB oder nur als Zeiger auf die Datei gespeichert sind, ausreicht, und arbeite daran, Ihr Modell so zu ändern, dass Daten zu den signifikanten Peaks gespeichert werden, die beim ersten Aufrufen der Daten identifiziert wurden lesen.


18

Ich führe einen Webanalysedienst mit etwa 50 Datenbankservern aus, von denen jeder viele Tabellen mit mehr als 100 Millionen Zeilen und einige mit mehr als einer Milliarde Zeilen enthält, manchmal bis zu zwei Milliarden (auf jedem Server).

Die Leistung hier ist in Ordnung. Es sind sehr normalisierte Daten. Mein Hauptanliegen beim Lesen ist jedoch, dass Sie die 4,2-Milliarden-Zeilen-Marke für diese Tabellen deutlich überschreiten (möglicherweise werden Sie nicht "ausgeführt", aber wahrscheinlich die anderen beiden), was bedeutet, dass Sie für BIGINT anstelle von INT verwenden müssen die Primär- / Fremdschlüssel.

Die MySQL-Leistung mit BIGINT-Feldern in einer indizierten Spalte ist im Vergleich zu INT lächerlich schrecklich . Ich habe den Fehler gemacht, dies einmal mit einem Tisch zu tun, von dem ich dachte, dass er über diese Größe hinauswachsen könnte, und als er ein paar hundert Millionen Zeilen erreichte, war die Leistung einfach miserabel. Ich habe keine rohen Zahlen, aber wenn ich schlecht sage, meine ich Windows ME schlecht.

Diese Spalte war der Primärschlüssel. Wir haben es wieder in ein INT und ein Presto Magico umgewandelt, die Leistung war wieder gut.

Alle unsere Server waren zu der Zeit auf Debian 5 und mit MySQL 5.0. Wir haben seitdem ein Upgrade auf Debian 6 und Percona MySQL 5.5 durchgeführt, sodass sich die Situation seitdem möglicherweise verbessert hat. Aber aufgrund meiner Erfahrungen hier denke ich nicht, dass es sehr gut funktionieren wird.


17

Unabhängig davon, ob es funktioniert oder nicht, bei einem einzelnen monolithischen Speichermedium tritt immer das gleiche Problem auf: Festplatten sind langsam. Bei 100 MB / s (ziemlich gut zum Drehen von Medien) dauert das Lesen einer 1-TB-Tabelle 3 Stunden . Dies setzt voraus, dass keine Analyse, Suche oder andere Verzögerungen Sie verlangsamen.

Aus diesem Grund verwendet fast jede "Big Data" -Installation einen verteilten Datenspeicher. Sie können 8-mal so viel Geld für die Erstellung eines fantastischen Computers für die Ausführung Ihrer Datenbank ausgeben. Wenn Sie jedoch eine Menge Daten haben, die parallel gescannt werden können, ist es fast immer besser, die Last auf die 8 billigeren Computer zu verteilen.

Projekte wie hadoop wurden speziell für solche Zwecke erstellt. Sie erstellen einen Cluster aus einer ganzen Reihe kostengünstiger Computer, verteilen die Daten auf alle und fragen sie parallel ab. Es ist nur eine von einem halben Dutzend Lösungen, die alle auf der gleichen Idee basieren, aber sie sind sehr beliebt.


13

Hm ... ich sehe zwei Gründe, warum Sie diese Art von Datenstruktur wählen würden:

  • Sie müssen wirklich jeden Datenpunkt mit allen Datenpunktabfragen vergleichen
  • Sie beabsichtigen, Ihre gesamte Logik in SQL auszuführen

Nun würde ich vorschlagen, sich eingehend mit Ihren Anforderungen zu befassen und zu überprüfen, ob mindestens eine der oben genannten Annahmen zutrifft. Wenn beides nicht zutrifft, machen Sie die Dinge nur langsamer. Für diese Art von Dataset würde ich vorschlagen, zunächst herauszufinden, wie auf die Daten zugegriffen werden soll, welche Genauigkeit Sie benötigen usw. - und dann Ihre Datenbank entsprechend zu gestalten.

PS: Denken Sie daran, dass Sie mindestens 36 + 5 Bytes pro Datenpunkt benötigen. Bei 200B Datenpunkten sollten Sie also mindestens 8,2 TB Speicherplatz benötigen.

PPS: Sie brauchen die idSpalte in der datapointsTabelle nicht, PRIMARY KEY (spectrum_id, index)wahrscheinlich ist eine ausreichend (achten Sie nur darauf, dass indexes sich um ein reserviertes Wort handelt).


12

BEARBEITEN:

Tun Sie dies nicht in MySQL, wenn Daten auf einer einzigen Festplatte gespeichert sind. Das Lesen dieser Datenmenge von einem einzelnen Medium dauert Stunden. Sie müssen SKALIEREN, NICHT NACH OBEN.

Und Sie müssen Ihre Daten denormalisieren, wenn Sie eine effektive Datenanalyse durchführen möchten. Sie entwerfen hier kein Online-System. Sie wollen Zahlen knacken, entsprechend gestalten.

Ursprüngliche Antwort unter der Zeile.


Die Antwort hängt von Ihren Fragen ab. MySQL ist möglicherweise nicht das beste Werkzeug für diesen Job. Möglicherweise möchten Sie nach Lösungen suchen, die Sie skalieren und nicht vergrößern können. Wenn Sie bereit sind, einige Anstrengungen zu unternehmen, sollten Sie sich vielleicht eine Map Reduce-Lösung wie Hadoop zulegen.

Wenn Sie mehr Ad-hoc-Anfragen stellen möchten, ist die BigQuery- Lösung von Google möglicherweise eine gute Lösung für Sie. Relevante Präsentation von Google I / O 2012: Big Data mit BigQuery zerkleinern

Die Lösung hängt also davon ab, ob es sich um eine einmalige Angelegenheit handelt und ob Sie Ad-hoc-Anfragen angemessen unterstützen möchten.


9

Niemand hat so meinen Vorschlag erwähnt. Werfen Sie einen Blick auf massiv beschädigte MySQL- Lösungen. Sehen Sie sich zum Beispiel diese hoch angesehene Tumblr-Präsentation an .

Das Konzept lautet:

  • Anstelle einer extra großen Datenbank
  • Verwenden Sie viele kleine, die Teile der Originaldaten enthalten

Auf diese Weise können Sie horizontal skalieren, anstatt die vertikale Leistung zu verbessern. Googles BigTable und GFS verwenden auch billige horizontal skalierbare Knoten, um Petabyte an Daten zu speichern und abzufragen.

Es wird jedoch Probleme geben, wenn Sie Abfragen über verschiedene Shards ausführen müssen.


Wenn jemand daran interessiert ist, habe ich vor einiger Zeit eine Hello-World-Sharding-Anwendung erstellt. Es wird hier in einem Blogbeitrag besprochen . Ich habe RavenDB und C # verwendet, aber die Details sind irrelevant und die Idee ist dieselbe.


7

Auf welcher Maschine werden die Daten gespeichert? Handelt es sich um gemeinsam genutzte Speichergeräte?

Der ultimative Faktor, der Ihre Abfragezeit bestimmt, werden Ihre Festplatten sein. Datenbanken und ihre Abfrageoptimierer sollen die Anzahl der Datenträger-E / A-Vorgänge so weit wie möglich reduzieren. Da Sie nur 3 Tabellen haben, ist dies ziemlich zuverlässig.

Die Lese- / Schreibgeschwindigkeit einer Festplatte ist 200- bis 300-mal langsamer als die Speichergeschwindigkeit. Suchen Sie nach Festplatten mit sehr hoher Latenz und hoher Lese- und Schreibgeschwindigkeit. Wenn sich all diese Daten auf einem 2-TB-Laufwerk befinden, werden Sie wahrscheinlich lange darauf warten, dass die Abfragen abgeschlossen werden. Die Festplattenlatenz beträgt ~ 10-15 Millisekunden, während die Speicherlatenz weniger als 10 Nanosekunden beträgt. Die Festplattenlatenz kann 1000-2000x langsamer sein als die Speicherlatenz. Das Bewegen des mechanischen Arms auf der Festplatte ist das LANGSAMSTE in diesem gesamten System.

Wie viel RAM hast du? 16 Gigabyte? Nehmen wir an, Sie können 32 Datensätze speichern. Sie haben 16000 Dateien. Wenn Sie alle Datenpunkte linear scannen, können Sie leicht allein 5-10 Sekunden Suchzeit haben. Berücksichtigen Sie dann die Übertragungsrate von 50mb / s? Über 7 Stunden. Darüber hinaus müssen temporär gespeicherte Daten auf der Festplatte gespeichert werden, um Platz für das Lesen neuer Daten zu schaffen.

Wenn Sie ein gemeinsam genutztes Speichergerät verwenden, das von anderen Benutzern aktiv genutzt wird, ist es am besten, wenn Sie alles nachts ausführen.

Reduzieren Sie die Anzahl der verschachtelten Abfragen hilft auch gut. Verschachtelte Abfragen führen zu temporären Tabellen, die Ihre Festplatte noch mehr auslasten. Ich hoffe, Sie haben genügend freien Speicherplatz auf Ihrer Festplatte.

Die Abfrageoptimierung kann jeweils nur eine Abfrage anzeigen. Verschachtelte select-Anweisungen können daher nicht optimiert werden. Wenn Sie jedoch wissen, dass eine bestimmte verschachtelte Abfrage dazu führt, dass ein kleiner Datensatz zurückgegeben wird, behalten Sie ihn bei. Bei der Abfrageoptimierung werden Histogramme und grobe Annahmen verwendet. Wenn Sie etwas über die Daten und die Abfrage wissen, können Sie dies tun.

Je mehr Sie wissen, wie Ihre Daten auf der Festplatte gespeichert sind, desto schneller können Sie Ihre Abfragen schreiben. Wenn alles nacheinander auf dem Primärschlüssel gespeichert wurde, kann es hilfreich sein, die von einer verschachtelten Abfrage zurückgegebenen Primärschlüssel zu sortieren. Wenn Sie die Menge der zu analysierenden Datensätze reduzieren können, tun Sie dies auch im Voraus. Abhängig von Ihrem System sehen Sie ungefähr 1 Sekunde Datenübertragung pro Datei.

Wenn Sie die Name-Werte (die Varchars) ändern, würde ich es in einen Datentyp mit einer maximalen Größe ändern, es wird eine Fragmentierung verhindern und der Kompromiss ist nur ein paar Bytes mehr Speicher. Vielleicht ein NVARCHAR mit maximal 100.

Soweit die Kommentare zur Denormalisierung der Tabelle. Ich denke, es ist am besten, die Datenpunkte in größeren Gruppen zu speichern (vielleicht als Spektren) und dann die Datenanalyse in Python oder einer Sprache durchzuführen, die mit der Datenbank interagiert. Es sei denn, Sie sind ein SQL-Assistent.


3
Sie betonen den großen Unterschied zwischen Festplatten- und Speicherlatenz, aber Ihre Zahlen sind um den Faktor 1000 niedriger. Wenn Festplatten eine Latenz von etwa 10 ms und Speicher 10 ns aufweisen, unterscheiden sich die Latenzen nicht um den Faktor 1000, sondern um den Faktor 1000 1.000.000!
Spectre256

6

Für mich klingt es nach einem Nutzungsszenario, in dem Sie so etwas wie einen "relationalen Spaltenspeicher" wie hier beschrieben wünschen .

Ich kann den Entwurf falsch verstehen, aber wenn Sie sich hauptsächlich mit einer großen Sammlung von Arrays befassen, bedeutet das Speichern in typischen zeilenorientierten Tabellen, dass jedes Element einem Slice ähnelt. Wenn Sie sich für die typische Betrachtung von Slices interessieren, ist dies sinnvoll, aber es kann weniger effizient sein, wenn Sie wirklich ganze Spalten gleichzeitig betrachten.

Beim Abrufen der Arrays müssen Sie sie möglicherweise nicht nur mit einer anderen Tabelle verknüpfen, die sich aus Ihrer Normalisierung ergibt, sondern Sie können die Reihe auch als Array und nicht als Hash abrufen.

Ich kann das Problem wirklich falsch verstehen und ich schlage nicht einmal eine spezifische Lösung vor.

Hier ist ein weiterer Vortrag , der möglicherweise relevant ist, auch wenn es sich nicht wirklich um eine aktuelle oder implementierbare Lösung handelt.


6

Ich würde empfehlen, dass Sie versuchen, Ihre Tabelle zu partitionieren. Wir haben über 80 Millionen Zeilen in einer einzigen Tabelle (Börsendaten) und haben keine Probleme, schnell darauf zuzugreifen.

Abhängig davon, wie Sie Ihre Daten durchsuchen möchten, sollten Sie Ihre Partitionen entwerfen. In unserem Fall funktioniert Datum gut, da wir nach bestimmten Daten fragen.

http://dev.mysql.com/doc/refman/5.1/de/partitioning-limitations.html

http://www.slideshare.net/datacharmer/mysql-partitions-tutorial


5

Ja aber...

Ich habe mit Tabellen gearbeitet, die 2 Milliarden Zeilen hatten. Es wurde jedoch erwartet, dass nur die Abfragen, die PK verwenden, schnell sind.

Am wichtigsten ist, dass die Hardware über genügend RAM verfügte, um ganze Tabellen in den Arbeitsspeicher aufzunehmen. Als dies zu einem Problem wurde (zu diesem Zeitpunkt waren es maximal 96 GB), entschied man sich für eine vertikale Partitionierung, wobei die Größe der auf jedem Computer festgelegten Tabelle klein genug war, um noch in den Arbeitsspeicher zu passen. Außerdem waren die Maschinen über 10-Gbit-Glasfaser verbunden, sodass der Netzwerkdurchsatz kein so großes Problem darstellte.

BTW. Ihr Schema sieht aus wie etwas, das in eine NoSQL-Lösung passen könnte, indem es run_idals Hashing-Schlüssel für Spektren und spectrum_idals Hashing-Schlüssel für Datenpunkte verwendet wird.


4

Ich habe in meinem Blog über dieses Thema geschrieben: http://www.tocker.ca/2013/10/24/improving-the-performance-of-large-tables-in-MySQL.html

Um einige der wichtigsten Punkte zu wiederholen:

  • B-Bäume werden mit zunehmender Größe schlechter und passen nicht in den Speicher (MySQL ist hier nicht alleine).
  • InnoDB verfügt über einige Funktionen, die zur Aufrechterhaltung der Leistung beitragen (Änderungspufferung; früher als "Puffer einfügen" bezeichnet).
  • Partitionierung kann auch helfen.

In den Kommentaren meines Beitrags hat Tim Callaghan dazu verlinkt: http://www.tokutek.com/resources/benchmark-results/benchmarks-vs-innodb-hdds/#iiBench

Das zeigt das Einfügen von 1 Milliarde Zeilen unter Verwendung des iibench-Benchmarks.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.