MySQL: Arbeiten mit 192 Billionen Datensätzen… (Ja, 192 Billionen)


39

Hier ist die Frage ...

Was sollten meine Überlegungen angesichts von 192 Billionen Datensätzen sein?

Mein Hauptanliegen ist die Geschwindigkeit.

Hier ist der Tisch ...

    CREATE TABLE `ref` (
  `id` INTEGER(13) AUTO_INCREMENT DEFAULT NOT NULL,
  `rel_id` INTEGER(13) NOT NULL,
  `p1` INTEGER(13) NOT NULL,
  `p2` INTEGER(13) DEFAULT NULL,
  `p3` INTEGER(13) DEFAULT NULL,
  `s` INTEGER(13) NOT NULL,
  `p4` INTEGER(13) DEFAULT NULL,
  `p5` INTEGER(13) DEFAULT NULL,
  `p6` INTEGER(13) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY (`s`),
  KEY (`rel_id`),
  KEY (`p3`),
  KEY (`p4`)
    );

Hier sind die Fragen ...

SELECT id, s FROM ref WHERE red_id="$rel_id" AND p3="$p3" AND p4="$p4"

SELECT rel_id, p1, p2, p3, p4, p5, p6 FROM ref WHERE id="$id"

INSERT INTO rel (rel_id, p1, p2, p3, s, p4, p5, p6)
VALUES ("$rel_id", "$p1", "$p2", "$p3", "$s", "$p4", "$p5", "$p6")

Hier sind einige Notizen ...

  • Die SELECT's werden viel häufiger ausgeführt als die INSERT. Gelegentlich möchte ich jedoch ein paar hundert Datensätze gleichzeitig hinzufügen.
  • Last-weise wird es stundenlang nichts geben, dann vielleicht ein paar tausend Abfragen auf einmal.
  • Glaube nicht, dass ich mich mehr normalisieren kann (brauche die p-Werte in einer Kombination)
  • Die gesamte Datenbank ist sehr relational.
  • Dies wird mit Abstand der größte Tisch sein (der nächstgrößere ist ungefähr 900.000).

UPDATE (08/11/2010)

Interessanterweise habe ich eine zweite Option gegeben ...

Anstelle von 192 Billionen könnte ich 2,6 * 10 ^ 16 (15 Nullen, was 26 Billionen bedeutet) speichern ...

Aber in dieser zweiten Option müsste ich nur eine Bigint (18) als Index in einer Tabelle speichern. Das war's - nur die eine Spalte. Ich würde also nur prüfen, ob ein Wert vorhanden ist. Hin und wieder Datensätze hinzufügen, nie löschen.

Das lässt mich denken, dass es eine bessere Lösung als mysql geben muss, um einfach Zahlen zu speichern ...

Sollte ich diese zweite Option annehmen oder bei der ersten bleiben ...

[edit] Ich habe gerade die Nachricht erhalten, dass einige Tests durchgeführt wurden - 100 Millionen Zeilen mit diesem Setup geben die Abfrage in 0,0004 Sekunden zurück. [/ edit]


7
Wie sehr setzen Sie MySQL dafür ein? Könnten Sie überzeugt sein, zu einem anderen DBMS zu wechseln, wenn jemand solide Argumente dafür liefert?
WheresAlice

3
Billionen wie in 10 ^ 12 oder wie in 10 ^ 18?
Andol

15
Bei 192 Billionen Datensätzen sollten Sie über ein Budget verfügen, mit dem Sie Fragen an MySQL-Committer stellen können, nicht an einige Diskussionsforen.
Remus Rusanu

5
Mit einer so großen Datenbank (und offensichtlich mit einem anständigen Budget) können Sie eine Oracle- oder SQL Server-Lösung verwenden, die erwiesenermaßen problemlos mit großen Datenbanken umgehen kann.
Jim B

5
Achten Sie darauf, uns auf dem Laufenden zu halten, wenn Sie dies implementieren. Das würde mich sicherlich interessieren. Vielleicht möchten Sie es auch für highscalability.com
Tom O'Connor

Antworten:


30

Die pQd-Schätzung von 7PB erscheint vernünftig, und das sind viele Daten für ein RDBMS. Ich bin mir nicht sicher, ob ich jemals von jemandem gehört habe, der 7PB mit einem gemeinsam genutzten Festplattensystem ausführt, geschweige denn mit MySQL. Das Abfragen dieses Datenvolumens mit einem gemeinsam genutzten Festplattensystem wird ungewöhnlich langsam. Die schnellste SAN-Hardware erreicht eine maximale Geschwindigkeit von 20 GB / s, selbst wenn große Streaming-Abfragen berücksichtigt werden. Wenn Sie sich SAN-Hardware dieser Spezifikation leisten können, können Sie sich etwas leisten, das für den Job besser geeignet ist als MySQL.

Tatsächlich habe ich Probleme, mir ein Szenario vorzustellen, in dem Sie ein Budget für ein Festplattensubsystem dieser Spezifikation haben könnten, aber nicht für eine bessere DBMS-Plattform. Selbst wenn Sie 600-GB-Festplatten (das derzeit größte 15-KB-Enterprise-Laufwerk auf dem Markt) verwenden, müssen Sie ungefähr 12.000 physische Festplatten mit einer Kapazität von 7PB speichern. SATA-Festplatten wären billiger (und mit 2-TB-Festplatten bräuchten Sie etwa 1/3 der Anzahl), aber einiges langsamer.

Ein SAN dieser Spezifikation von einem großen Anbieter wie EMC oder Hitachi würde viele Millionen Dollar kosten. Als ich das letzte Mal mit SAN-Geräten eines großen Anbieters zusammengearbeitet habe, lagen die Kosten für die Übertragung von Speicherplatz auf einem IBM DS8000 über 10.000 GBP / TB, ohne Kapital für die Controller.

Sie brauchen wirklich ein Shared-Nothing-System wie Teradata oder Netezza für so viele Daten. Das Sharden einer MySQL-Datenbank könnte funktionieren, ich würde jedoch eine eigens dafür erstellte VLDB-Plattform empfehlen. Mit einem Shared-Nothing-System können Sie auch viel kostengünstigere Direct-Attach-Festplatten für die Knoten verwenden.

Sie müssen auch Ihre Leistungsanforderungen berücksichtigen.

  • Was ist eine akzeptable Laufzeit für eine Abfrage?
  • Wie oft werden Sie Ihren Datensatz abfragen?
  • Kann der Großteil der Abfragen mithilfe eines Index gelöst werden (dh, es wird ein kleiner Teil der Daten (beispielsweise weniger als 1%) untersucht), oder muss ein vollständiger Tabellenscan durchgeführt werden?
  • Wie schnell werden Daten in die Datenbank geladen?
  • Benötigen Ihre Abfragen aktuelle Daten oder könnten Sie mit einer regelmäßig aktualisierten Berichtstabelle leben?

Kurz gesagt, das stärkste Argument gegen MySQL ist, dass Sie Backflips durchführen würden, um eine angemessene Abfrageleistung über 7PB an Daten zu erzielen, wenn dies überhaupt möglich ist. Dieses Datenvolumen versetzt Sie wirklich in das Gebiet des Shared-Nothing, um etwas zu erstellen, das es relativ schnell abfragt, und Sie benötigen wahrscheinlich eine Plattform, die von Anfang an für den Shared-Nothing-Betrieb konzipiert wurde. Alleine die Festplatten werden die Kosten einer vernünftigen DBMS-Plattform in den Schatten stellen.

Hinweis: Wenn Sie Ihre Betriebs- und Berichtsdatenbanken aufteilen, müssen Sie nicht unbedingt für beide dieselbe DBMS-Plattform verwenden. Schnelle Einfügungen und Berichte im Sekundentakt aus derselben 7PB-Tabelle zu erhalten, wird zumindest eine technische Herausforderung sein.

Ausgehend von Ihren Kommentaren, dass Sie mit einer gewissen Latenz bei der Berichterstellung leben können, ziehen Sie möglicherweise separate Erfassungs- und Berichterstattungssysteme in Betracht, und Sie müssen möglicherweise nicht alle 7PB-Daten in Ihrem Betriebserfassungssystem aufbewahren. Stellen Sie sich eine betriebsbereite Plattform wie Oracle (MySQL kann dies mit InnoDB tun) für die Datenerfassung vor (wiederum werden die Kosten für die Festplatten allein die Kosten für das DBMS in den Schatten stellen, es sei denn, Sie haben viele Benutzer) und eine VLDB-Plattform wie Teradata, Sybase IQ, RedBrick, Netezza (Hinweis: proprietäre Hardware) oder Greenplum für die Berichterstellung


1
@ConcernedOfTunbridgeW - sie können immer so vorgehen : blog.backblaze.com/2009/09/01/… - viel mehr Spaß als SAN, nur ~ 120-130 4U-Boxen erforderlich ... aber ich bin mir nicht sicher, ob 'die business 'würde sich freuen ....
pQd

Im Grunde genommen ein Sun Thumper mit kleinem Budget und ein echtes Beispiel für eine Option für einen Knoten in einem Shared-Nothing-System. Ich bin mir sicher, dass ich auch andere Optionen dafür gesehen habe, aber ich kann mir nicht vorstellen, wo. Die Frage ist nicht so sehr, welche Hardware, sondern welche Datenbankplattform.
ConcernedOfTunbridgeWells

Interessierte Beobachter werden jedoch feststellen, dass jede Art von Direct-Attach-Box wie diese viel, viel billiger pro TB ist als alles, was auf einem SAN basiert .
ConcernedOfTunbridgeWells

@ConcernedOfTunbridgeWells und Sie können all diese Abfragen / Wartungen und alles andere parallel auf mehreren [ansonsten stromhungrigen] Boxen ausführen.
pQd

1
@ConcernedOfTunbridgeWells - um Ihre Fragen zu beantworten ... Ich benötige ungefähr 500 Anfragen, um in weniger als einer Sekunde zurückzukehren, wenn möglich. Ich mache das nur ein paar hundert Mal am Tag. Wenn eine Abfrage ausgeführt wird, muss die vollständige Tabelle gescannt werden. Auch die INSERTs haben eine niedrigere Priorität als die SELECTs, so dass sie nicht annähernd augenblicklich sein müssen. Ich kann ein paar Stunden warten, bis "neue" Daten in die Datenbank eingehen.
Sarah

16

Scherbe es. Bei dieser Größe ist eine einzige große Instanz ein Selbstmord - denken Sie an mögliche Backup-Wiederherstellungen, Tabellenbereichsverfälschungen, das Hinzufügen neuer Spalten oder andere "Housekeeping" -Prozesse - all dies ist in dieser Größenordnung nicht in angemessener Zeit möglich.

einfache Berechnung der Rückseite der Hüllkurve - unter der Annahme von 32-Bit-Ganzzahlen für alle Spalten mit Ausnahme der 64-Bit-ID; keine Indizes enthalten:

8 * 4B + 8B = 40B pro Zeile [und das ist sehr optimistisch]

192 Billionen Zeilen 40B ergeben jeweils fast 7 PB

Vielleicht können Sie das Ganze überdenken, Informationen für eine schnelle Berichterstellung zusammenfassen und komprimierte Aufzeichnungen für bestimmte Zeitintervalle speichern, wenn jemand tiefergehende Details untersuchen muss.

zu beantwortende Fragen:

  • Was ist eine akzeptable Ausfallzeit für den Fall, dass das System abstürzt oder neu gestartet wird?
  • Auf welche Ausfallzeiten kann zugegriffen werden, wenn Sie ein Backup wiederherstellen oder den Server für die geplante Wartung aus der Produktion nehmen müssen?
  • Wie oft und wo möchten Sie sichern?

Zufällige Links - Geschwindigkeit der Einfügungen:


Ich stimme zu - 7PB ist ziemlich schwer. Ich würde es lieben, es neu zu überdenken und eine leichtere Lösung zu finden, aber ich muss die Existenz (oder Nichtexistenz) einer bestimmten Kombination der p-Felder finden. Das Aufteilen der Tabellen kam mir in den Sinn - es ist sinnvoller, aber dann heißt es nur, dass ich die Abfrage für jede Tabelle nacheinander habe. In wie viele Tabellen würden Sie sich aus Interesse hier aufteilen?
Sarah

5
@ Sarah - Ich würde nicht nur empfehlen, in Tabellen zu teilen, sondern auch Maschinen. Sie können Ihre Abfragen parallel ausführen, um die Leistung zu verbessern. Was ist mit Dateisystembeschädigungen oder sogar einer routinemäßigen Überprüfung nach dem Neustart des Servers? Ich bin mir nicht sicher, was Sie mit der Suche nach einer bestimmten Kombination meinen. Vielleicht würde ein einfacher Schlüsselwertspeicher helfen? Tabellengröße - nicht mehr als einige Dutzend GB; Daten auf einem Server - nicht mehr als wenige TB. Schauen Sie sich stackoverflow.com/questions/654594 an, um zu erfahren , welche Kopfschmerzen in einem viel kleineren Maßstab zu erwarten sind. benutze innodb_file_per_table
pQd


2

Es kann auch eine andere Möglichkeit geben, als Billiarden von Zahlen zu speichern, wenn Sie nur sehen möchten, ob sie sich im Set befinden. Bloom-Filter sind eine probabilistische Methode, indem sie auf verschiedene Arten gehasht werden. Auch falsch positive Ergebnisse sind möglich, falsch negative jedoch nicht. (Also könnte es heißen, dass die Nummer im Set ist - und falsch ist, aber es wird nicht gesagt, dass sie nicht da ist, wenn es wirklich so ist). Es gibt auch immer noch ein Problem mit der großen Anzahl der zu speichernden Elemente, aber es könnte zumindest die Größe des Arbeitsdatensatzes etwas verringern.


Klingt interessant, obwohl ich mit falschen Negativen leben könnte - aber nicht mit den falschen Positiven :)
Sarah

2

Bearbeiten: Eigentlich, wenn es nur das Vorhandensein oder Nichtvorhandensein eines "Datensatzes" an Position X in einer Reihe von ganzen Zahlen ist, könnten Sie den Datenspeicher entfernen und einfach die Bitmap verwenden ... Also, 10 oder so Maschinen mit 100 TB Festplattenspeicher (Sie haben also 10 Kopien Ihrer Bitmap für Leistung und Sicherung). Wenn Sie 128 GB RAM pro Server haben, können Sie einen Blockgruppenindex mit hoher Auflösung in den Speicher einfügen, um eine erste Überprüfung durchzuführen, bevor Sie auf die Festplatte für Bit X von 26 Billiarden zugreifen .

Ich würde Option 2 wählen, wenn Sie Folgendes nehmen:

375 Maschinen mit jeweils 64 TB (32 2 TB Laufwerke) (realistisch 400 Maschinen für Ausfälle) ordnen die Datensätze dann einfach ZVOLs zu, die jeweils 2 TB groß sind. Speichern Sie dann auf einem oder mehreren Indexservern in einem Judy-Array oder einem Critbit-Array oder einer einfachen Bitmap die Zuordnung, ob Sie diesem 1 von 26 Billiarden Speicherorten einen Datensatz hinzugefügt haben. Der Index würde zwischen 50 und 100 TB liegen, und Sie könnten sogar einen Index der zweiten Ebene haben, der angibt, ob Datensätze in einen bestimmten 64-KB-Adressblock geschrieben wurden, der in weniger als 64 GB RAM passt und eine schnelle Erstprüfung ermöglicht ob eine bestimmte "Nachbarschaft" leer war oder nicht.

Um diesen Datensatz zu lesen, überprüfen Sie zunächst anhand des Index, ob ein Datensatz gefunden werden kann. Wenn dies der Fall ist, gehen Sie zu Maschine Nr. (X) / ZOL Nr. (Y) auf dieser Maschine. Die Suche nach einzelnen Datensätzen wäre extrem schnell und Sie könnten testen, ob einige Teile des Datenspeichers in verschiedene Datenbanken geladen wurden (während Sie den Datenspeicher für die eigentliche Arbeit verwenden) und Leistungstests durchführen, um festzustellen, ob sie die gesamte Datenbank unterstützen können - oder nicht. Verwenden Sie den Datenspeicher einfach so.

Eine ZOL ist eine ZFS-Sache, die man sich in anderen Dateisystemen als eine spärliche Datei vorstellen könnte, sodass ähnliche Dinge zutreffen würden. Sie können auch nur auf eine bestimmte Bytenummer auf einer Festplatte indizieren. Dies ist jedoch schwierig, wenn die Festplatten unterschiedlich groß sind, wenn Sie die Anzahl der pro Festplatte verwendeten Bytes nicht auf ein für alle Festplatten gültiges Niveau begrenzen - dh 1,75 TB pro 2 TB Festplatte . Oder erstellen Sie Metadevices mit fester Größe usw.


Hallo Sarah, ich bin mir nicht sicher, ob Sie noch daran arbeiten, aber wenn Sie Hilfe benötigen, könnte ich meine Idee für Sie auf einer 100-TB-Maschine prototypisieren und wäre auch bereit, Hosting (in einem großen US-Rechenzentrum) und Verwaltung des gesamten Produktionsclusters von 400-500 Maschinen nach Bedarf. Übrigens, haben Sie jemals bei CNET in SF gearbeitet?

1

Abgesehen von der Optimierung Ihrer DB-Parameter wie crazy (verwenden Sie mysqltuner, um zu helfen), um zu versuchen, Ihre SELECTs so weit wie möglich zwischengespeichert zu halten, ist START TRANSACTION / CoMMIT (unter der Annahme von InnoDB) beim Einfügen Ihrer wenigen hundert Datensätze eine Sache, die Sie möglicherweise untersuchen Reihe für Reihe den Overhead sperren und die Einfügezeit um einen großen Faktor verkürzen. Ich würde die Tabelle auch als MyISAM und InnoDB erstellen und Tests darauf ausführen, um zu sehen, was wirklich schneller ist, wenn Sie das Caching verschärft haben. Es ist nicht immer so, dass MyISAM schneller zum Lesen ist.

http://www.mysqlperformanceblog.com/2007/01/08/innodb-vs-myisam-vs-falcon-benchmarks-part-1/

Während des Tests sollte die Anzahl der gleichzeitigen Threads ebenfalls nach oben und unten variiert werden, bis Sie herausfinden, wie viel RAM Sie sich auf dem Server leisten können, um die Caches zu optimieren. Möglicherweise stellen Sie fest, dass Sie zwar mathematisch mehr Threads unterstützen können, die Datenbank selbst jedoch möglicherweise eine schlechtere Leistung erzielt, wenn die Thread-Anzahl zu hoch ist.

Wenn Sie MyISAM und / oder InnoDB file-per-table verwenden, können Sie auch untersuchen, ob Sie einen anderen Dateisystem-Mount-Punkt für / var / lib / mysql erstellen, der auf eine kleinere Blockgröße und die Parameter vom Typ fs abgestimmt wurde - dh ext3 / Mit ext4 / resiserfs können Sie data = writeback für das Journal verwenden und die Aktualisierung der Zugriffszeiten auf das Dateisystem aus Gründen der E / A-Geschwindigkeit deaktivieren.


1
myisam scheint aufgrund von Transaktionsanforderungen nicht in Frage zu kommen.
pQd 08.08.10

0

Für die zweite Option, wie viele Zahlen werden wahrscheinlich tatsächlich platziert?

Wenn es nur eine von tausend oder 10K, 100K usw. gibt, können durch das Speichern von Bereichen mit verwendeten (oder nicht verwendeten) Zahlen Billionen von Einträgen eingespart werden. Beispiel: Speichern ('frei', 0,100000), ('belegt', 100000,100003), ('frei', 100004,584234) - Aufteilen von Zeilen in zwei oder drei Zeilen nach Bedarf und Indizieren auf die erste Zahl, Suche nach x <= {needle}, um zu sehen, ob der Bereich mit der gesuchten Nummer belegt oder frei ist.

Möglicherweise benötigen Sie nicht beide Status. Speichern Sie einfach den Status, der am wenigsten wahrscheinlich ist.

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.