Hintergrund :
Ich habe eine Webanwendung erstellt, die ich relativ gut skalieren möchte. Ich weiß, dass ich nicht Google oder Twitter bin, aber meine App verwendet eine ziemlich große Datenmenge für jeden Benutzer und hat daher ziemlich hohe Datenanforderungen. Ich möchte bereit sein, einigermaßen gut zu skalieren, ohne später alles neu entwerfen zu müssen.
Ich betrachte mich als Softwareentwickler, nicht als Datenbankexperte. Deshalb poste ich hier. Hoffentlich kann mir jemand mit viel mehr Datenbankkenntnissen Ratschläge geben.
Mit einer relativ großen Anzahl von Benutzern, aber nichts wie Facebook-Nummern, erwarte ich eine Datenbank, die so aussieht:
Ein "großer Tisch":
- 250 Millionen Datensätze
- 20 Spalten
- Ungefähr 100 GB Daten
- Hat einen indizierten Bigint (20) Fremdschlüssel
- Hat eine indizierte varchar (500) string_id-Spalte
- Hat eine int (11) "Wert" -Spalte
4 weitere Tabellen:
- Jeweils 10 Millionen Datensätze
- Jeweils ca. 2 - 4 GB Daten
- Jede dieser Tabellen hat 4 - 8 Spalten
- Eine Spalte ist datetime date_created
- Eine Spalte ist die Spalte varchar (500) string_id
- In einem Join werden eine oder zwei Spalten aus jeder dieser Tabellen ausgewählt
Eine dieser Tabellen wird zum Speichern von Durchschnittswerten verwendet. Das Schema lautet bigint (20) id, varchar (20) string_id, datetime date_created, float durchschnitt_value
Was ich tun möchte - zwei relativ teure Abfragen:
Berechnen Sie neue Durchschnittswerte:
- Wählen Sie mit einem Fremdschlüssel bis zu mehrere Millionen separate Datensätze aus der großen Tabelle aus.
- Berechnen Sie einen neuen Durchschnitt, gruppieren Sie nach der string_id.
- Fügen Sie die Ergebnisse in die Durchschnittstabelle ein.
- Wie derzeit erstellt, verwendet diese Abfrage zwei Verknüpfungen.
Erstellen Sie de-normalisierte, schreibgeschützte Datensätze für Benutzer:
- Verwenden Sie einen Fremdschlüssel, um zwischen 1.000 und 40.000 Datensätze aus der großen Tabelle auszuwählen.
- Verbinden Sie sich mit jeder der anderen vier Tabellen im neuesten Datensatz mit der Zeichenfolgen-ID-Spalte.
- Fügen Sie die Ergebnisse in eine de-normalisierte Tabelle ein.
- Diese Datensätze werden vom Front-End verwendet, um Benutzern Informationen anzuzeigen.
- Wie derzeit erstellt, verwendet diese Abfrage vier Verknüpfungen.
Ich plane, jede dieser teuren Abfragen in einer Batch-Back-End-Datenbank auszuführen, die ihre Ergebnisse an einen Echtzeit-Front-End-DB-Server überträgt, der Anforderungen von Benutzern verarbeitet. Diese Abfragen werden in regelmäßigen Abständen ausgeführt. Ich habe nicht entschieden, wie oft. Die durchschnittliche Abfrage könnte möglicherweise einmal pro Tag durchgeführt werden. Die De-Normalisierungsabfrage muss häufiger ausgeführt werden - möglicherweise alle paar Minuten.
Jede dieser Abfragen wird derzeit in MySQL in wenigen Sekunden auf einem sehr einfachen Computer mit einem Datensatz mit 100.000 Datensätzen in der „großen Tabelle“ ausgeführt. Ich bin sowohl besorgt über meine Skalierbarkeit als auch über die Kosten der Skalierung.
Fragen :
- Scheint dieser Ansatz sinnvoll? Stimmt etwas aus einer Gesamtperspektive offensichtlich nicht?
- Ist ein RDBMS das richtige Tool, oder sollte ich mir andere "Big Data" -Lösungen wie die der Hadoop-Familie ansehen? Meine Neigung ist es, ein RDBMS zu verwenden, da die Daten strukturiert sind und gut in das relationale Modell passen. Ab einem bestimmten Punkt kann ich jedoch möglicherweise kein RDBMS mehr verwenden. Ist das wahr? Wann würde dieser Schalter benötigt?
- Wird es funktionieren? Können diese Abfragen in angemessener Zeit ausgeführt werden? Ich kann vielleicht Stunden auf Abfrage Nr. 1 warten, aber Abfrage Nr. 2 sollte in Minuten abgeschlossen sein.
- Was muss ich aus Hardware-Sicht beachten? Was sind meine RAM- und CPU-Engpässe wahrscheinlich? Ich gehe davon aus, dass es wichtig ist, Indizes im RAM zu halten. Gibt es noch etwas, das ich berücksichtigen sollte?
- Irgendwann muss ich wahrscheinlich meine Daten partitionieren und mehrere Server verwenden. Scheint mein Anwendungsfall bereits in dieser Kategorie zu sein, oder kann ich eine einzelne Maschine für eine Weile vertikal skalieren? Funktioniert das mit dem 10-fachen der Daten? 100x?
Antworten:
Haben Sie versucht, mehr Daten zu stapeln und zu vergleichen? 100K Zeilen spielen keine Rolle. Probieren Sie 250M oder 500M aus, wie Sie es erwarten, und sehen Sie, wo die Engpässe liegen.
Ein RDBMS kann viele Dinge tun, wenn Sie die Einschränkungen genau beachten und versuchen, mit den Stärken des Systems zu arbeiten. Sie sind in einigen Dingen außergewöhnlich gut und in anderen schrecklich. Sie müssen also experimentieren, um sicherzugehen, dass sie richtig passen.
Bei einigen Stapelverarbeitungsjobs können Sie Flatfiles wirklich nicht schlagen, die Daten in den Arbeitsspeicher laden, sie mit einer Reihe von Schleifen und temporären Variablen zerschlagen und die Ergebnisse ausgeben. MySQL wird niemals in der Lage sein, diese Geschwindigkeit zu erreichen, aber wenn es richtig eingestellt und richtig verwendet wird, kann es in einer Größenordnung liegen.
Sie möchten lediglich untersuchen, wie Ihre Daten partitioniert werden können. Haben Sie einen großen Datensatz mit zu vielen Querverbindungen, um ihn aufteilen zu können, oder gibt es natürliche Orte, an denen Sie ihn partitionieren können? Wenn Sie es partitionieren können, haben Sie nicht eine Tabelle mit einem ganzen Stapel von Zeilen, sondern möglicherweise viele wesentlich kleinere. Kleinere Tabellen mit viel kleineren Indizes weisen tendenziell eine bessere Leistung auf.
Aus Hardware-Sicht müssen Sie testen, wie Ihre Plattform funktioniert. Manchmal ist das Gedächtnis wichtig. In anderen Fällen handelt es sich um Festplatten-E / A. Es hängt wirklich davon ab, was Sie mit den Daten machen. Sie müssen genau auf Ihre CPU-Auslastung achten und nach hohen E / A-Werten suchen, um zu wissen, wo das Problem liegt.
Teilen Sie Ihre Daten nach Möglichkeit auf mehrere Systeme auf. Sie können MySQL Cluster verwenden, wenn Sie sich mutig fühlen, oder einfach viele unabhängige Instanzen von MySQL starten, in denen jeweils ein beliebiger Teil des gesamten Datensatzes mithilfe eines sinnvollen Partitionierungsschemas gespeichert wird.
quelle
Übersichtstabellen.
Berechnen Sie jeden Tag aggregierte Informationen für die Tagesdaten. Tragen Sie das in die "Zusammenfassung" -Tabelle (n) ein. Stellen Sie Ihre Fragen gegen sie. Leicht 10 mal so schnell.
Für weitere Informationen geben Sie bitte an
Einige offensichtliche Dinge ...
"Kleiner -> zwischenspeicherbarer -> schneller
quelle
Wenn Sie Ihre Front-End-Daten bereitstellen möchten, können Sie es nicht übertreffen, Trigger zum Einfügen in materialisierte Ansichten zu verwenden, die mit dem Back-End synchronisiert, aber für die Bereitstellung der Daten optimiert sind, es sei denn, es gibt ständig viele Einfügungen. Natürlich müssen Sie Joins usw. usw. in diesen Triggern auf ein Minimum beschränken. Eine Strategie, die ich verwendet habe, besteht darin, diese Einfügungen / Aktualisierungen in eine Zwischentabelle zu stellen und sie dann jede Minute oder so weiterzuleiten. Es ist viel einfacher, einen Datensatz zu senden als 4 GB Datensätze. Das Streamen von 4 GB Daten dauert lange, selbst wenn Sie die gesuchten Datensätze schnell finden.
Ich stimme Tadman zu. Am besten profilieren Sie es mit der Art von Daten, die Sie für die Art von System erwarten, die Sie möchten.
quelle