Eine Partitionierung nach HASH
wird
hauptsächlich eingesetzt, um eine gleichmäßige Verteilung der
Daten auf eine im Voraus festgelegte Anzahl von Partitionen zu
erzielen. Bei einer Bereichs- oder Listenpartitionierung müssen
Sie explizit angeben, in welcher Partition Spaltenwerte
gespeichert werden sollen, während MySQL Ihnen dies bei einer
Hash-Partitionierung abnimmt. Hier müssen Sie lediglich einen
Spaltenwert oder einen auf einem Spaltenwert basierenden
Ausdruck für den Hash angeben und sagen, auf wie viele
Partitionen die partitionierte Tabelle verteilt werden soll.
Um eine Tabelle mit einer
HASH
-Partitionierung aufzuteilen, müssen Sie
an die CREATE TABLE
-Anweisung eine
PARTITION BY HASH
(
-Klausel anfügen,
wobei expr
)expr
ein Ausdruck ist, der
einen Integer zurückgibt. Das kann auch einfach der Name einer
Spalte sein, die einen der Integer-Typen von MySQL hat.
Zusätzlich wird normalerweise noch eine PARTITIONS
-Klausel angefügt,
wobei num
num
ein nichtnegativer Integer
ist und angibt, auf wie viele Partitionen die Tabelle verteilt
werden soll.
Die folgende Anweisung erzeugt beispielsweise eine Tabelle, die
einen Hash der Spalte store_id
verwendet und
auf 4 Partitionen verteilt wird:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT, store_id INT ) PARTITION BY HASH(store_id) PARTITIONS 4;
Wenn Sie keine PARTITIONS
-Klausel verwenden,
ist die Anzahl der Partitionen nach Voreinstellung
1
. Ausnahme:
Bei NDB Cluster
-Tabellen ist die vorgegebene
Anzahl der Partitionen gleich der Anzahl der Datenknoten im
Cluster, eventuell berichtigt um eine
MAX_ROWS
-Einstellung, um zu gewährleisten,
dass alle Zeilen in die Partitionen hineinpassen. (Siehe
Kapitel 16, MySQL Cluster.)
Wenn Sie das Schlüsselwort PARTITIONS
ohne
darauf folgende Zahlenangabe verwenden, wird ein Syntaxfehler
ausgelöst.
Sie können für expr
auch einen
SQL-Ausdruck einsetzen, der einen Integer zurückliefert. Wenn
Sie Ihre Tabelle beispielsweise anhand des Einstellungsjahres
der Angestellten partitionieren möchten, gehen Sie
folgendermaßen vor:
CREATE TABLE employees ( id INT NOT NULL, fname VARCHAR(30), lname VARCHAR(30), hired DATE NOT NULL DEFAULT '1970-01-01', separated DATE NOT NULL DEFAULT '9999-12-31', job_code INT, store_id INT ) PARTITION BY HASH( YEAR(hired) ) PARTITIONS 4;
Sie können für expr
alle Funktionen
und Ausdrücke verwenden, die in MySQL zulässig sind,
vorausgesetzt, der Rückgabewert ist ein nichtkonstanter,
nichtzufälliger Integer. (Mit anderen Worten: Der Wert soll
variieren, aber deterministisch sein.) Sie müssen allerdings
daran denken, dass dieser Ausdruck jedes Mal, wenn eine Zeile
eingefügt, aktualisiert oder eventuell auch gelöscht wird,
ausgewertet werden muss. Das bedeutet, dass komplexe Ausdrücke
die Leistung beeinträchtigen können, insbesondere, wenn
Operationen ausgeführt werden, die viele Zeilen auf einmal
betreffen (wie etwa Masseneinfügungen).
Am effizientesten sind Hash-Funktionen, die nur eine einzige Tabellenspalte bearbeiten und deren Wert mit dem Spaltenwert konsistent zu- oder abnimmt, da hierdurch ein „Pruning“ von Partitionsbereichen möglich wird. D. h.: Je enger sich der Wert des Ausdrucks an dem Wert der zugrunde liegenden Spalte orientiert, umso effizienter kann MySQL ihn für die Hash-Partitionierung einsetzen.
Wenn beispielsweise date_col
eine Spalte vom
Typ DATE
ist, dann ändert sich der Ausdruck
TO_DAYS(date_col)
unmittelbar mit dem Wert
von date_col
, da jede Änderung des Werts von
date_col
auch den Wert des Ausdrucks ändert,
und zwar in völlig konsistenter Form. Der Ausdruck
YEAR(date_col)
ändert sich bei
date_col
-Änderungen nicht ganz so
unmittelbar wie TO_DAYS(date_col)
, da nicht
jede Änderung in date_col
eine entsprechende
Änderung in YEAR(date_col)
nach sich zieht.
Dennoch ist auch YEAR(date_col)
ein guter
Kandidat für eine Hash-Funktion, da es sich direkt mit einem
Teil von date_col
ändert und nicht die
Gefahr besteht, dass eine Änderung von
date_col
zu einer unverhältnismäßigen
Änderung von YEAR(date_col)
führt.
Nehmen wir dagegen an, Sie hätten eine Spalte namens
int_col
vom Typ INT
. Nun
betrachten Sie den Ausdruck POW(5-int_col,3) +
6
. Dieser wäre ganz schlecht als Hash-Funktion
geeignet, da nicht garantiert ist, dass Änderungen von
int_col
proportionale Änderungen im Wert des
Ausdrucks nach sich ziehen. Wenn Sie den Wert von
int_col
um einen gegebenen Betrag ändern,
können dadurch ganz unterschiedliche Änderungen im Wert des
Ausdrucks eintreten. Ändern Sie beispielsweise
int_col
von 5
in
6
, so ändert sich der Wert des Ausdrucks um
-1
, ändern Sie dagegen
int_col
von 6
in
7
, so ändert sich der Wert des Ausdrucks um
-7
.
Mit anderen Worten: Je enger der Graph des Spaltenwerts im
Verhältnis zum Wert des Ausdrucks einer geraden Linie folgt,
wie sie durch die Gleichung
y=
vorgegeben
ist, wenn n
xn
eine von null
verschiedene Konstante ist, umso besser eignet sich der Ausdruck
für das Hashing. Denn je weniger linear ein Ausdruck ist, umso
ungleichmäßiger werden die Daten auf die Partitionen verteilt,
die dieser Ausdruck anlegt.
Theoretisch ist bei Ausdrücken, an denen mehrere Spaltenwerte beteiligt sind, auch Pruning möglich, aber es kann schwierig und langwierig sein, herauszufinden, welche dieser Ausdrücke nun wirklich für Pruning geeignet sind. Daher sind Hashing-Ausdrücke mit mehreren Spalten nicht sonderlich zu empfehlen.
Wenn PARTITION BY HASH
verwendet wird,
ermittelt MySQL anhand des Modulus des Ergebnisses der
Benutzerfunktion, welche von num
Partitionen verwendet wird. Anders ausgedrückt: Für einen
Ausdruck expr
wird der Datensatz in
der Partition N
gespeichert, wobei
ist. Nehmen wir
beispielsweise an, Tabelle N
=
MOD(expr
,
num
)t1
ist
folgendermaßen definiert, sodass sie 4 Partitionen hat:
CREATE TABLE t1 (col1 INT, col2 CHAR(5), col3 DATE) PARTITION BY HASH( YEAR(col3) ) PARTITIONS 4;
Wenn Sie in t1
einen Datensatz einfügen,
dessen col3
-Wert
'2005-09-15'
ist, dann wird die Partition, in
der er gespeichert wird, folgendermaßen ermittelt:
MOD(YEAR('2005-09-01'),4) = MOD(2005,4) = 1
MySQL 5.1 unterstützt auch eine Variante der
HASH
-Partitionierung namens
lineares Hashing, die einen komplexen
Algorithmus einsetzt, um neu in eine partitionierte Tabelle
eingefügte Zeilen zu platzieren. Eine Beschreibung dieses
Algorithmus finden Sie unter
Abschnitt 17.2.3.1, „LINEAR HASH
-Partitionierung“.
Die Benutzerfunktion wird bei jeder Einfügung oder Aktualisierung und unter Umständen auch bei einer Löschung eines Datensatzes ausgewertet.
Hinweis: Wenn die Tabelle, die
partitioniert werden soll, einen
UNIQUE
-Schlüssel hat, müssen Spalten, die
als Argumente an die HASH
-Benutzerfunktion
oder die column_list
des
KEY
s übergeben werden, Teil dieses
Schlüssels sein.
Dies ist eine Übersetzung des MySQL-Referenzhandbuchs, das sich auf dev.mysql.com befindet. Das ursprüngliche Referenzhandbuch ist auf Englisch, und diese Übersetzung ist nicht notwendigerweise so aktuell wie die englische Ausgabe. Das vorliegende deutschsprachige Handbuch behandelt MySQL bis zur Version 5.1.