Tabellen in MySQL aufteilen. Gute Übung?


14

Ich habe begonnen, an einem vorhandenen Projekt zu arbeiten, und der vorherige Entwickler hatte eine Tabelle in 10 separate Tabellen mit identischen Schemata, aber unterschiedlichen Daten aufgeteilt.

Die Tabellen sehen folgendermaßen aus:

[tableName_0]
[tableName_1]
[tableName_2]
[tableName_3]
[tableName_4]
[tableName_5]
[tableName_6]
[tableName_7]
[tableName_8]
[tableName_9]

Der Primärschlüssel ist ein ganzzahliges idFeld. Die Anwendung verwendet einen Hash-Algorithmus ( idMod 10), um zu ermitteln, auf welche Tabelle beim Nachschlagen zugegriffen werden soll. Zum Beispiel würde id= 10 ergeben [tableName_0].

Zusammen haben die Tabellen wahrscheinlich 100.000 Zeilen und die Wachstumsrate ist relativ niedrig.

Meine Frage ist also, ob dies eine praktikable Lösung ist oder ob es in jeder Situation eine gute Praxis ist. Meine Theorie ist, darauf zu drängen, sie zu kombinieren, da es die Dinge so weit wie möglich einfacher macht UNION. Der Hauptnachteil besteht darin, den gesamten Anwendungscode zu ändern und festzustellen, ob er sich auf lange Sicht überhaupt lohnt.

Antworten:


16

Ich denke, jeder macht das zu kompliziert. Der entscheidende Punkt hier ist:

Zusammen haben die Tabellen wahrscheinlich 100.000 Zeilen und die Wachstumsrate ist relativ niedrig.

Dies ist ein Kinderspiel für jedes RDBMS. Gehen Sie mit einer Tabelle, indizieren Sie sie richtig und betrachten Sie sie als gelöstes Problem.

Sie müssen keine Partitionierung in Betracht ziehen, egal ob "hausgemacht" oder auf andere Weise, bis Sie beginnen, extrem große Datenmengen zu verarbeiten - denken Sie an Milliarden von Zeilen und mehr.


3

Sie können Zusammenführungstabellen verwenden, diese sind jedoch älter als die 4.x-Versionen. Wenn Ihre Anwendung manuell partitioniert wurde, weil entweder a) Sie eine sehr alte Version ausführen oder b) der ursprüngliche Entwickler keine Kenntnis von Tabellenpartitionen hatte.

Kurz gesagt, wenn Sie 5.1+ ausführen, können Sie mysql diese Partitionierung für Sie durchführen lassen. Siehe http://dev.mysql.com/doc/refman/5.1/en/partitioning.html Wenn Sie 5.5 verwenden, sollten Sie diese spezifischen Dokumente überprüfen, da Sie einige Unterschiede feststellen.

Partitionierung hat viele Vorteile. Es hängt jedoch wirklich von dem vorliegenden Datensatz, den Zugriffsmustern und der Art und Weise ab, wie er indiziert werden soll. Beachten Sie auch, dass meine folgenden Kommentare im Zusammenhang mit der Partitionierung von mysql 5+ stehen, NICHT mit älteren mysql Merge-Tabellen. obwohl sie manchmal in Bezug auf Partitionen diskutiert werden.

Einige Beispiele:

  • Straight Bucketing (oder Hashing) basierend auf häufig verwendeten Suchschlüsseln. Wenn Sie so gut wie immer nach einem Primärschlüssel oder einem anderen eindeutigen Schlüssel suchen, kann mysql den Suchraum um den Faktor der Anzahl Ihrer Partitionen verringern. Beachten Sie jedoch, dass dies nachteilig sein kann, wenn Sie nach einem Schlüssel partitionieren und dann häufig nach einem anderen Schlüssel suchen. Wenn Sie nach einem Schlüssel suchen, dessen Daten nicht partitioniert sind, müssen WEITERE Suchvorgänge für Suchvorgänge durchgeführt werden (einer für jede Partition, ehrlich gesagt, es ist nicht bekannt, wo sich die Daten befinden).
  • Stellen Sie sich Situationen vor, in denen Sie über einen zeitlich begrenzten Satz von Datensätzen verfügen, der nach Datum wächst, und in denen Sie den vorherigen Monat regelmäßig entfernen. Wenn Sie nach Datum partitionieren, können Sie einfach eine Partition löschen, die genauso schnell ist wie das Löschen einer Tabelle, egal wie groß. Wenn Sie eine solche Tabelle nach Datum bereinigen würden, müssten Sie eine oder mehrere DELETE-Abfragen ausführen, bei denen jede einzelne Zeile gelöscht wird. Der Nachteil dabei ist, dass mysql nicht automatisch neue Partitionen erstellt, sobald Sie das maximale Datum erreicht haben, das Sie in diesem Szenario berücksichtigt haben. Sie benötigen zusätzliche Wartungsskripte, die in Ihrem Teil erstellt wurden, um Partitionen nach Bedarf hinzuzufügen.
  • Wenn Sie myisam verwenden, sind Überprüfungen und Wiederherstellungen viel schneller. Betrachten Sie eine 100G Myisam-Tabelle. Wenn Sie eine abgestürzte Tabelle wiederherstellen möchten, benötigen Sie mindestens etwa 100 GB freien Speicherplatz. Wenn es in 10 verschiedene Blöcke gleicher Größe aufgeteilt wurde, benötigen Sie nur 10 GB Speicherplatz (und weniger key_sort_buffer-Speicher für eine schnelle Wiederherstellung). Müsste aber für jede Partition eine Iteration machen.

Zusammenfassend kann der allgemeine Ansatz der Partitionierung von Tabellen viele Vorteile bieten. Es ist jedoch kein Wundermittel, blind angewendet zu werden, ohne Rücksicht auf Zugriffsmuster und wie genau Sie partitionieren.

Ich könnte mir Situationen vorstellen, in denen die gewünschte Partitionierung sehr anwendungsspezifisch ist und besser geeignet wäre, diese Logik in der Anwendungsschicht zu haben. Angesichts Ihrer Beschreibung des geraden Moduls 10 scheint dies jedoch kein solcher Fall zu sein.

BEARBEITEN

Beim Aufschreiben meiner Beschreibung habe ich vergessen, dass Sie angegeben haben, dass Ihre Tabelle 100.000 Zeilen enthält. Ohne das vollständige Schema Ihrer Tabelle und die durchschnittliche Zeilenlänge ist es schwer zu sagen, aber im Allgemeinen klingt das selbst für bescheidene Hardware mittelgroß. Zur gleichen Zeit, wenn es keine Probleme verursacht, wie es jetzt oder in absehbarer Zeit ist, dann nimm dir keine Zeit und führe Risiken ein, indem du es änderst.


3

Was der vorherige Entwickler für Sie getan hat, ist eine eigene Implementierung von Partition-by-Hash. MySQL unterstützt dies buchstäblich von Haus aus mit MySQL 5.1:

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

Ich kann mir keinen guten Grund vorstellen, also implementiere deine eigene Partition-by-Hash, anstatt dich auf die native Version zu verlassen [1]. Das Durchführen von Schemaänderungen wird ein Albtraum.

Ich empfehle auch selten Partition-by-Hash (die native Implementierung). Ich denke, es wäre nützlich, wenn Sie es verwenden könnten, um jede der Partitionen gleichzeitig zu durchsuchen (was MySQL nicht tun wird). Wenn Sie mehrere Partitionen durchsuchen müssen, ist das von Ihnen beschriebene Schema häufig viel langsamer.

[1] Für einige der anderen Partitionstypen kann es jedoch sinnvoll sein, eine eigene Partitionierung zu erstellen. MySQL zwingt Sie, Ihren Partitionsschlüssel Teil Ihres Primärschlüssels und aller eindeutigen Indizes zu machen.


2

Als Antwort auf die Frage:

ist, ob dies eine praktikable Lösung ist oder nicht

IMHO, das scheint unnötiger Overhead zu sein. Sie können eine einzelne Tabelle einfach indizieren und richtig partitionieren, es sei denn, die Beschreibung enthält weitere Informationen.

Als Antwort auf die Frage:

... wenn es in jeder Situation eine gute Übung ist

Meiner Meinung nach kann vertikales Sharding je nach Kontext sinnvoll sein. Wenn ich das sehe, liegt es normalerweise in einer Art Protokollform vor. Nehmen wir an, wir verwenden dies für Webserver-Protokolle und möchten nach Monaten partitionieren. Anstatt eine vorhandene Tabelle jeden Tag zu ändern, könnten wir jeden Tag eine neue Tabelle erstellen und Zeilen in dieser Tabelle protokollieren.

Stellen Sie sich beispielsweise vor, eine Web-Log-Tabelle hätte die Form:

datetime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
uri VARCHAR(1024),
host VARCHAR(255),
user_agent VARCHAR(255),
etc...

Ihre Lösung erstellt nach Bedarf Tabellen in der Weblog-Datenbank:

weblogs.20120301
weblogs.20120302
weblogs.20120303

etc.

Auf diese Weise bleiben die Daten pflegbar und durchsuchbar. Die Extraktion wird zu einem normalen periodischen Vorgang. Kontinuierliche Vorgänge werden nicht durch Vorgänge mit älteren Daten gesperrt.

In dem von Ihnen vorgestellten Szenario sind Sie sowieso an eine Struktur gebunden. Warum also nicht eine einzelne Tabelle verwenden, die für diesen Zweck optimiert wurde? Die algorithmische Speicherung von Zeilen erscheint lückenhaft und fehleranfällig.


0

Wenn eine Abfrage auf enorme Datenmengen abzielt, führt die Aufteilung der Daten nach Abfragebedingungen zu einer deutlichen Verbesserung der Leistung. Aber wie Sie gesehen haben, wirft eine solche Aufteilung einige Programmierprobleme auf.

Die Frage ist also: Ist diese Aufteilung für die Leistung wert oder schadet sie der Leistung?

Wenn bei einer Transaktion mehrere Zeilen über mehrere Tabellen hinweg gesperrt werden müssen und Probleme auftreten (z. B. Deadlock oder Transaktions-Timeout), können Sie diese zu einer einzigen Tabelle zusammenfassen und die SQL neu schreiben, um die Probleme zu beheben.

Wenn ich darüber nachdachte, ob ich eine Tabelle aufteilen sollte, dachte ich über den Kompromiss zwischen Leistungssteigerung und Programmierkomplexität nach.

In Ihrer Situation kann die Änderung des vorhandenen Codes eine langfristige Lösung sein, um die Wartung des Codes zu vereinfachen. Ich würde einen Versuch zur Metaprogrammierung vorschlagen. Beispiel: Verwenden von StringTemplate zum dynamischen Generieren von SQL. Ich mag es, SQL aus der Meta-Programming-Engine zu generieren, wenn die Modifikation des vorhandenen Codes zu schwierig ist.


0

Wenn Sie Dateien in einer Tabelle speichern müssen, können Sie diese Metodologie zum Exportieren, Reparieren und Wiederherstellen verwenden.

Ich habe Tabellen mit> 30 GB in 10 Tabellen aufgeteilt. Diese Tabellen haben nur ID - BLOB und sind für mich leicht zu behalten. Und ich benutze MyISAM, um INNODB-Puffer zu speichern.

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.