Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL-Leistung:mehrere Tabellen vs. Indizes für einzelne Tabellen und Partitionen

20.000 Tabellen zu erstellen ist eine schlechte Idee. Sie werden bald 40.000 Tische benötigen und dann noch mehr.

Ich habe dieses Syndrom Metadata Tribbles genannt in meinem Buch SQL Antipatterns . Sie sehen dies jedes Mal, wenn Sie planen, eine „Tabelle pro X“ oder eine „Spalte pro X“ zu erstellen.

Dies führt zu echten Leistungsproblemen, wenn Sie Zehntausende von Tabellen haben. Jede Tabelle erfordert, dass MySQL interne Datenstrukturen, Dateideskriptoren, ein Datenwörterbuch usw. verwaltet.

Es gibt auch praktische betriebliche Konsequenzen. Möchten Sie wirklich ein System erstellen, bei dem Sie jedes Mal, wenn sich ein neuer Benutzer anmeldet, einen neuen Tisch erstellen müssen?

Stattdessen würde ich Ihnen empfehlen, MySQL-Partitionierung zu verwenden .

Hier ist ein Beispiel für die Partitionierung der Tabelle:

CREATE TABLE statistics (
  id INT AUTO_INCREMENT NOT NULL,
  user_id INT NOT NULL,
  PRIMARY KEY (id, user_id)
) PARTITION BY HASH(user_id) PARTITIONS 101;

Dadurch haben Sie den Vorteil, dass Sie eine logische Tabelle definieren und die Tabelle für einen schnelleren Zugriff in viele physische Tabellen unterteilen, wenn Sie einen bestimmten Wert des Partitionsschlüssels abfragen.

Wenn Sie beispielsweise eine Abfrage wie in Ihrem Beispiel ausführen, greift MySQL nur auf die richtige Partition zu, die die spezifische user_id enthält:

mysql> EXPLAIN PARTITIONS SELECT * FROM statistics WHERE user_id = 1\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: statistics
   partitions: p1    <--- this shows it touches only one partition 
         type: index
possible_keys: NULL
          key: PRIMARY
      key_len: 8
          ref: NULL
         rows: 2
        Extra: Using where; Using index

Die HASH-Partitionierungsmethode bedeutet, dass die Zeilen durch einen Modulus des ganzzahligen Partitionsschlüssels in einer Partition platziert werden. Dies bedeutet zwar, dass viele user_ids auf dieselbe Partition abgebildet werden, aber jede Partition würde im Durchschnitt nur 1/N-mal so viele Zeilen haben (wobei N die Anzahl der Partitionen ist). Und Sie definieren die Tabelle mit einer konstanten Anzahl von Partitionen, sodass Sie sie nicht jedes Mal erweitern müssen, wenn Sie einen neuen Benutzer bekommen.

Sie können eine beliebige Anzahl von Partitionen bis zu 1024 (oder 8192 in MySQL 5.6) auswählen, aber einige Leute haben Leistungsprobleme gemeldet, wenn sie so hoch gehen.

Es wird empfohlen, eine Primzahl von Partitionen zu verwenden. Falls Ihre user_id-Werte einem Muster folgen (z. B. wenn Sie nur gerade Zahlen verwenden), hilft die Verwendung einer Primzahl von Partitionen dabei, die Daten gleichmäßiger zu verteilen.

Beantworten Sie Ihre Fragen im Kommentar:

Wenn Sie für die HASH-Partitionierung 101 Partitionen verwenden, wie ich im obigen Beispiel zeige, dann hat jede gegebene Partition im Durchschnitt etwa 1 % Ihrer Zeilen. Sie sagten, Ihre Statistiktabelle hat 30 Millionen Zeilen. Wenn Sie also diese Partitionierung verwenden, hätten Sie nur 300.000 Zeilen pro Partition. Das ist für MySQL viel einfacher zu lesen. Sie können (und sollten) auch Indizes verwenden – jede Partition hat ihren eigenen Index, und dieser ist nur 1 % so groß wie der Index für die gesamte unpartitionierte Tabelle.

Die Antwort auf die Frage, wie Sie eine angemessene Anzahl von Partitionen bestimmen können, lautet also:Wie groß ist Ihre gesamte Tabelle und wie groß sollen die Partitionen im Durchschnitt sein?

Die Anzahl der Partitionen muss nicht unbedingt wachsen, wenn Sie die HASH-Partitionierung verwenden. Letztendlich haben Sie vielleicht insgesamt 30 Milliarden Zeilen, aber ich habe festgestellt, dass wenn Ihr Datenvolumen um Größenordnungen wächst, dies sowieso eine neue Architektur erfordert. Wenn Ihre Daten so groß werden, benötigen Sie wahrscheinlich Sharding über mehrere Server sowie Partitionierung in mehrere Tabellen.

Allerdings können Sie eine Tabelle mit ALTER TABLE:

neu partitionieren
ALTER TABLE statistics PARTITION BY HASH(user_id) PARTITIONS 401;

Dies muss die Tabelle neu strukturieren (wie die meisten ALTER TABLE-Änderungen), also rechnen Sie damit, dass es eine Weile dauern wird.

Möglicherweise möchten Sie die Größe von Daten und Indizes in Partitionen überwachen:

SELECT table_schema, table_name, table_rows, data_length, index_length
FROM INFORMATION_SCHEMA.PARTITIONS
WHERE partition_method IS NOT NULL;

Wie bei jeder Tabelle möchten Sie, dass die Gesamtgröße der aktiven Indizes in Ihren Pufferpool passt, denn wenn MySQL während SELECT-Abfragen Teile der Indizes in den Pufferpool hinein und aus ihm heraus austauschen muss, leidet die Leistung.

Wenn Sie die RANGE- oder LIST-Partitionierung verwenden, ist das Hinzufügen, Löschen, Zusammenführen und Teilen von Partitionen viel häufiger. Siehe http://dev.mysql. com/doc/refman/5.6/en/partitioning-management-range-list.html

Ich ermutige Sie, den manuellen Abschnitt über Partitionierung zu lesen , und sehen Sie sich auch diese nette Präsentation an:Boost Performance Mit MySQL 5.1-Partitionen .