MySQL Partitionierung für große Datensätze

MySQLBeginner
Jetzt üben

Einführung

In diesem Lab lernen Sie, wie Sie MySQL-Partitionierung für große Datensätze implementieren, um die Abfrageleistung und die Datenverwaltung zu verbessern. Das Lab konzentriert sich auf die Partitionierung einer Tabelle nach Bereich (range), insbesondere unter Verwendung der Spalte sale_date einer sales-Tabelle.

Sie beginnen mit der Verbindung zum MySQL-Server und der Erstellung einer sales_data-Datenbank. Anschließend erstellen Sie die sales-Tabelle und partitionieren sie nach dem Jahr der sale_date in Partitionen für 2020, 2021, 2022, 2023 und eine zukünftige Partition. Nachfolgende Schritte umfassen das Abfragen von Daten aus bestimmten Partitionen, das Reorganisieren von Partitionen mit ALTER TABLE und die Überprüfung der Auswirkungen der Partitionierung auf die Abfragegeschwindigkeit.

Hinweis: Für dieses Lab müssen Sie die MySQL-Shell nur einmal zu Beginn aufrufen und am Ende beenden. Alle SQL-Befehle in den folgenden Schritten sollten innerhalb derselben MySQL-Sitzung ausgeführt werden.

Erstellen einer partitionierten Tabelle

In diesem Schritt erstellen wir eine Datenbank und eine partitionierte Tabelle in MySQL. Partitionierung hilft bei der Verwaltung großer Datensätze, indem eine Tabelle basierend auf einer bestimmten Regel in kleinere, besser handhabbare Teile aufgeteilt wird. Dies kann die Abfrageleistung erheblich verbessern, insbesondere bei Abfragen, die Daten basierend auf dem Partitionierungsschlüssel filtern.

Öffnen Sie zuerst ein Terminal in der LabEx VM. Sie sollten sich bereits im Verzeichnis ~/project befinden.

Verbinden Sie sich als Root-Benutzer mit dem MySQL-Server (tun Sie dies nur einmal zu Beginn des Labs):

sudo mysql -u root

Sie befinden sich nun in der MySQL-Shell. Alle nachfolgenden SQL-Befehle sollten in dieser Sitzung ausgeführt werden, bis Sie das Lab beenden.

Lassen Sie uns eine Datenbank namens sales_data erstellen, um unsere Tabelle zu speichern:

CREATE DATABASE sales_data;

Wechseln Sie zur neu erstellten Datenbank:

USE sales_data;

Nun erstellen wir eine Tabelle namens sales und partitionieren sie nach dem Jahr der Spalte sale_date. Wir erstellen Partitionen für die Jahre 2020, 2021, 2022, 2023 und eine Auffangpartition für zukünftige Daten.

CREATE TABLE sales (
    sale_id INT NOT NULL,
    sale_date DATE NOT NULL,
    amount DECIMAL(10, 2) NOT NULL,
    PRIMARY KEY (sale_id, sale_date)
)
PARTITION BY RANGE (YEAR(sale_date)) (
    PARTITION p2020 VALUES LESS THAN (2021),
    PARTITION p2021 VALUES LESS THAN (2022),
    PARTITION p2022 VALUES LESS THAN (2023),
    PARTITION p2023 VALUES LESS THAN (2024),
    PARTITION pFuture VALUES LESS THAN MAXVALUE
);

Lassen Sie uns die Klausel PARTITION BY RANGE erläutern:

  • PARTITION BY RANGE (YEAR(sale_date)): Dies gibt an, dass die Tabelle basierend auf dem Bereich der Werte partitioniert wird, die von der Funktion YEAR() auf die Spalte sale_date angewendet werden.
  • PARTITION p2020 VALUES LESS THAN (2021): Dies erstellt eine Partition namens p2020. Jede Zeile, bei der das Jahr von sale_date kleiner als 2021 ist (d. h. 2020), wird in dieser Partition gespeichert.
  • PARTITION p2021 VALUES LESS THAN (2022): Dies erstellt eine Partition namens p2021 für Daten aus dem Jahr 2021.
  • PARTITION p2022 VALUES LESS THAN (2023): Dies erstellt eine Partition namens p2022 für Daten aus dem Jahr 2022.
  • PARTITION p2023 VALUES LESS THAN (2024): Dies erstellt eine Partition namens p2023 für Daten aus dem Jahr 2023.
  • PARTITION pFuture VALUES LESS THAN MAXVALUE: Dies erstellt eine Partition namens pFuture, die alle Daten mit einem sale_date-Jahr größer oder gleich 2024 speichert. MAXVALUE ist ein spezieller Wert, der immer größer als jeder andere Wert ist.

Nachdem Sie die CREATE TABLE-Anweisung ausgeführt haben, können Sie die Tabellenstruktur und ihre Partitionen mit dem folgenden Befehl überprüfen:

SHOW CREATE TABLE sales;

Suchen Sie in der Ausgabe nach der Klausel PARTITION BY RANGE, um zu bestätigen, dass die Tabelle mit den angegebenen Partitionen erstellt wurde.

Lassen Sie uns nun einige Beispieldaten in die sales-Tabelle einfügen. MySQL wird jede Zeile automatisch basierend auf dem sale_date in die richtige Partition einfügen.

INSERT INTO sales (sale_id, sale_date, amount) VALUES
(1, '2020-12-31', 100.00),
(2, '2021-01-15', 150.00),
(3, '2021-12-25', 200.00),
(4, '2022-06-01', 120.00),
(5, '2022-12-31', 180.00),
(6, '2023-03-10', 250.00),
(7, '2023-09-20', 300.00),
(8, '2024-01-01', 350.00);

Sie haben erfolgreich eine partitionierte Tabelle erstellt und Daten darin eingefügt. Im nächsten Schritt lernen wir, wie man Daten aus bestimmten Partitionen abfragt.

Daten aus spezifischen Partitionen abfragen

In diesem Schritt untersuchen wir, wie Daten effizient aus einer partitionierten Tabelle abgefragt werden können, indem wir spezifische Partitionen anvisieren. Dies ist einer der Hauptvorteile der Partitionierung, da sie es MySQL ermöglicht, nur die relevanten Partitionen zu scannen, wodurch die verarbeitete Datenmenge erheblich reduziert und die Abfrageleistung verbessert wird.

Erinnerung: Sie sollten sich immer noch in der MySQL-Shell befinden und die Datenbank sales_data verwenden. Falls nicht, verwenden Sie:

USE sales_data;

Um Daten aus einer spezifischen Partition abzufragen, können Sie eine WHERE-Klausel einfügen, die auf den Partitionierungsschlüssel filtert. Der Abfrageoptimierer von MySQL ist oft intelligent genug, um basierend auf der WHERE-Klausel zu identifizieren, welche Partitionen relevant sind.

Um beispielsweise alle Verkäufe aus dem Jahr 2021 abzurufen, können Sie die folgende Abfrage verwenden. Beachten Sie, dass wir eine direkte Bereichsbedingung für sale_date verwenden. Die Verwendung von Funktionen wie YEAR(sale_date) in der WHERE-Klausel kann verhindern, dass MySQL die Partition Pruning (Partitionen ausschließen) nutzt, was dazu führen würde, dass alle Partitionen gescannt werden.

SELECT * FROM sales WHERE sale_date >= '2021-01-01' AND sale_date < '2022-01-01';

Um zu sehen, welche Partitionen MySQL für diese Abfrage verwendet, können Sie die Anweisung EXPLAIN PARTITIONS verwenden:

EXPLAIN PARTITIONS SELECT * FROM sales WHERE sale_date >= '2021-01-01' AND sale_date < '2022-01-01';

In der Ausgabe von EXPLAIN PARTITIONS schauen Sie in die Spalte partitions. Sie sollte p2021 anzeigen, was darauf hindeutet, dass MySQL nur die Partition p2021 scannt, um diese Abfrage zu erfüllen.

+----+-------------+-------+------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | sales | p2021      | ALL  | PRIMARY       | NULL | NULL    | NULL |    2 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+-------------+

Sie können auch Daten abfragen, die sich über mehrere Partitionen erstrecken. Um beispielsweise Verkaufsdaten für die Jahre 2022 und 2023 zu erhalten:

SELECT * FROM sales WHERE sale_date >= '2022-01-01' AND sale_date < '2024-01-01';

Wenn Sie erneut EXPLAIN PARTITIONS verwenden, wird angezeigt, dass MySQL sowohl die Partitionen p2022 als auch p2023 verwendet:

EXPLAIN PARTITIONS SELECT * FROM sales WHERE sale_date >= '2022-01-01' AND sale_date < '2024-01-01';

Die Spalte partitions zeigt p2022,p2023 an.

+----+-------------+-------+---------------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | partitions    | type | possible_keys | key  | key_len | ref  | rows | Extra       |
+----+-------------+-------+---------------+------+---------------+------+---------+------+------+-------------+
|  1 | SIMPLE      | sales | p2022,p2023   | ALL  | PRIMARY       | NULL | NULL    | NULL |    4 | Using where |
+----+-------------+-------+---------------+------+---------------+------+---------+------+------+-------------+

Dies zeigt, wie die Partitionierung es MySQL ermöglicht, irrelevante Partitionen während der Abfrageausführung zu beschneiden (auszuschließen), was zu schnelleren Ergebnissen führt, insbesondere bei sehr großen Tabellen, bei denen das Scannen der gesamten Tabelle zeitaufwendig wäre.

Um die Anzahl der Zeilen in jeder Partition anzuzeigen, können Sie die Tabelle INFORMATION_SCHEMA.PARTITIONS abfragen:

SELECT
    PARTITION_NAME,
    TABLE_ROWS
FROM
    INFORMATION_SCHEMA.PARTITIONS
WHERE
    TABLE_SCHEMA = 'sales_data' AND TABLE_NAME = 'sales';

Diese Abfrage bietet eine klare Übersicht darüber, wie die Daten über Ihre Partitionen verteilt sind.

+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p2020          |          1 |
| p2021          |          2 |
| p2022          |          2 |
| p2023          |          2 |
| pFuture        |          1 |
+----------------+------------+

Sie haben erfolgreich Daten aus spezifischen Partitionen abgefragt und beobachtet, wie MySQL die Partitionierung zur Abfrageoptimierung nutzt.

Partitionen reorganisieren und verwalten

In diesem Schritt lernen wir, wie die Partitionsstruktur einer bestehenden Tabelle mit der Anweisung ALTER TABLE geändert wird. Dies ist nützlich, um Ihr Partitionierungsschema anzupassen, wenn Ihre Daten wachsen oder sich Ihre Anforderungen ändern.

Erinnerung: Sie sollten sich immer noch in der MySQL-Shell befinden und die Datenbank sales_data verwenden. Falls nicht, verwenden Sie:

USE sales_data;

Nehmen wir an, wir möchten eine neue Partition für das Jahr 2024 hinzufügen. Derzeit befinden sich Daten für 2024 und darüber hinaus in der Partition pFuture. Sie können keine neue Partition mit ADD PARTITION hinzufügen, da die Partition pFuture mit VALUES LESS THAN MAXVALUE definiert ist, was immer die letzte Partition sein muss.

Stattdessen müssen wir die Partition pFuture mit REORGANIZE aufteilen. Wir werden pFuture in zwei neue Partitionen aufteilen: eine für das Jahr 2024 (p2024) und eine neue pFuture-Partition für alles danach.

ALTER TABLE sales REORGANIZE PARTITION pFuture INTO (
    PARTITION p2024 VALUES LESS THAN (2025),
    PARTITION pFuture VALUES LESS THAN MAXVALUE
);

Dieser Befehl nimmt die bestehende Partition pFuture, verschiebt alle Daten für 2024 in die neue Partition p2024 und definiert pFuture neu, um Daten ab 2025 abzudecken. Die Zeile mit sale_date '2024-01-01' wird nach p2024 verschoben.

Lassen Sie uns die aktualisierte Partitionsstruktur und die Zeilenanzahl überprüfen:

SELECT
    PARTITION_NAME,
    TABLE_ROWS
FROM
    INFORMATION_SCHEMA.PARTITIONS
WHERE
    TABLE_SCHEMA = 'sales_data' AND TABLE_NAME = 'sales';

Sie sollten die neue Partition p2024 sehen. Die Zeile aus dem Jahr 2024 befindet sich nun in p2024.

+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p2020          |          0 |
| p2021          |          2 |
| p2022          |          2 |
| p2023          |          2 |
| p2024          |          0 |
| pFuture        |          0 |
+----------------+------------+

Lassen Sie uns nun das Zusammenführen von Partitionen demonstrieren. Angenommen, wir möchten die Partitionen p2020 und p2021 zu einer einzigen Partition namens p2020_2021 zusammenführen.

ALTER TABLE sales REORGANIZE PARTITION p2020, p2021 INTO (
    PARTITION p2020_2021 VALUES LESS THAN (2022)
);

Dieser Befehl fasst die Daten aus p2020 und p2021 in einer neuen Partition namens p2020_2021 zusammen. Die Klausel VALUES LESS THAN (2022) definiert die neue Grenze für diese zusammengeführte Partition.

Überprüfen Sie die Partitionsstruktur erneut:

SELECT
    PARTITION_NAME,
    TABLE_ROWS
FROM
    INFORMATION_SCHEMA.PARTITIONS
WHERE
    TABLE_SCHEMA = 'sales_data' AND TABLE_NAME = 'sales';

Sie werden sehen, dass p2020 und p2021 verschwunden sind und p2020_2021 mit der kombinierten Zeilenanzahl existiert.

+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p2020_2021     |          3 |
| p2022          |          2 |
| p2023          |          2 |
| p2024          |          0 |
| pFuture        |          0 |
+----------------+------------+

Schließlich lassen Sie uns eine Partition löschen. Wir können die Partition p2024 entfernen. Beachten Sie, dass dadurch auch alle Daten innerhalb dieser Partition gelöscht werden.

ALTER TABLE sales DROP PARTITION p2024;

Überprüfen Sie die Partitionsstruktur ein letztes Mal:

SELECT
    PARTITION_NAME,
    TABLE_ROWS
FROM
    INFORMATION_SCHEMA.PARTITIONS
WHERE
    TABLE_SCHEMA = 'sales_data' AND TABLE_NAME = 'sales';

Die Partition p2024 sollte nicht mehr aufgelistet sein.

+----------------+------------+
| PARTITION_NAME | TABLE_ROWS |
+----------------+------------+
| p2020_2021     |          3 |
| p2022          |          2 |
| p2023          |          2 |
| pFuture        |          0 |
+----------------+------------+

Sie haben erfolgreich Partitionen mit ALTER TABLE reorganisiert, zusammengeführt und gelöscht. Dies demonstriert die Flexibilität der Verwaltung partitionierter Tabellen, während sich Ihre Daten weiterentwickeln.

Auswirkungen von Partitionen auf die Abfragegeschwindigkeit prüfen

In diesem Schritt untersuchen wir, wie sich die Partitionierung auf die Abfrageleistung auswirken kann. Obwohl unser aktueller Datensatz klein ist, können wir dennoch das Prinzip des Partition Pruning (Ausschluss von Partitionen) beobachten, bei dem MySQL nur die notwendigen Partitionen scannt. Bei größeren Datensätzen ist dieser Effekt wesentlich ausgeprägter.

Erinnerung: Sie sollten sich immer noch in der MySQL-Shell befinden und die Datenbank sales_data verwenden. Falls nicht, verwenden Sie:

USE sales_data;

Um den Einfluss der Partitionierung zu beobachten, können wir die Anweisung EXPLAIN verwenden, die den Ausführungsplan einer Abfrage anzeigt. Insbesondere EXPLAIN PARTITIONS zeigt an, welche Partitionen abgerufen werden.

Führen wir eine Abfrage aus, die nach dem Partitionierungsschlüssel (Jahr von sale_date) filtert:

EXPLAIN PARTITIONS SELECT * FROM sales WHERE sale_date >= '2023-01-01' AND sale_date < '2024-01-01';

Beobachten Sie die Spalte partitions in der Ausgabe. Sie sollte anzeigen, dass nur die Partition p2023 gescannt wird.

Führen wir nun eine Abfrage aus, die nicht direkt nach dem Partitionierungsschlüssel, sondern nach einer anderen Spalte (amount) filtert:

EXPLAIN PARTITIONS SELECT * FROM sales WHERE amount > 200;

In diesem Fall, da die Abfragebedingung nicht direkt auf dem Partitionierungsschlüssel (sale_date) liegt, muss MySQL möglicherweise mehrere oder alle Partitionen scannen, um die übereinstimmenden Zeilen zu finden. Die Spalte partitions in der Ausgabe von EXPLAIN PARTITIONS zeigt an, welche Partitionen berücksichtigt wurden. Bei unserem kleinen Datensatz werden möglicherweise immer noch alle Partitionen gescannt.

Um einen detaillierteren Einblick in den Abfrageausführungsprozess und die aufgewendete Zeit zu erhalten, können Sie die Profiling-Funktion von MySQL verwenden.

Profiling aktivieren:

SET profiling = 1;

Führen Sie nun die beiden Abfragen erneut aus:

SELECT * FROM sales WHERE sale_date >= '2023-01-01' AND sale_date < '2024-01-01';
SELECT * FROM sales WHERE amount > 200;

Zeigen Sie die Profiling-Ergebnisse an:

SHOW PROFILES;

Die Ausgabe listet die ausgeführten Abfragen und ihre Dauer auf. Sie können dann die Details einer bestimmten Abfrage anhand ihrer Query_ID untersuchen:

SHOW PROFILE FOR QUERY [Query_ID];

Ersetzen Sie [Query_ID] durch die ID der Abfrage, die Sie aus der Ausgabe von SHOW PROFILES analysieren möchten. Betrachten Sie die verschiedenen Ausführungsphasen und die darin aufgewendete Zeit.

Obwohl der Zeitunterschied bei unserem kleinen Datensatz vernachlässigbar sein mag, werden Abfragen in realen Szenarien mit Millionen von Zeilen, die Partition Pruning nutzen können (wie die Abfrage, die nach YEAR(sale_date) filtert), erheblich schneller sein als diejenigen, die mehrere oder alle Partitionen scannen müssen.

Deaktivieren Sie schließlich das Profiling:

SET profiling = 0;

Dieser Schritt hat gezeigt, wie EXPLAIN PARTITIONS und Profiling verwendet werden, um zu verstehen, wie sich die Partitionierung auf die Abfrageausführung und -leistung auswirkt.

Zusammenfassung

In diesem Lab haben Sie gelernt, wie Sie MySQL-Partitionierung für große Datensätze implementieren, um die Abfrageleistung und die Datenverwaltung zu verbessern. Sie haben damit begonnen, eine Datenbank und eine Tabelle zu erstellen, die nach dem Jahr einer Datumsspalte per Bereich partitioniert ist. Anschließend haben Sie geübt, Daten aus bestimmten Partitionen abzufragen und beobachtet, wie MySQL Partition Pruning zur Optimierung von Abfragen nutzt. Schließlich haben Sie gelernt, wie Sie Partitionen durch Hinzufügen, Aufteilen und Zusammenführen mit der Anweisung ALTER TABLE reorganisieren und wie Sie mit EXPLAIN PARTITIONS und Profiling den Einfluss der Partitionierung auf die Abfragegeschwindigkeit verstehen können. Partitionierung ist eine leistungsstarke Technik zur effizienten Verwaltung und Abfrage großer Tabellen in MySQL.

Wenn Sie alle Schritte abgeschlossen haben, können Sie die MySQL-Shell verlassen, indem Sie Folgendes eingeben:

exit;