MariaDB
 sql >> Datenbank >  >> RDS >> MariaDB

Verwenden von Sysbench zum Generieren von Testdaten für Sharded-Tabellen in MySQL

Sysbench ist ein großartiges Tool, um Testdaten zu generieren und MySQL OLTP-Benchmarks durchzuführen. Üblicherweise würde man einen Vorbereitungs-Lauf-Bereinigungszyklus durchführen, wenn man Benchmarks mit Sysbench durchführt. Standardmäßig ist die von Sysbench generierte Tabelle eine standardmäßige Nicht-Partitions-Basistabelle. Dieses Verhalten kann natürlich erweitert werden, aber Sie müssen wissen, wie man es in das LUA-Skript schreibt.

In diesem Blogbeitrag zeigen wir Ihnen, wie Sie mit Sysbench Testdaten für eine partitionierte Tabelle in MySQL generieren. Dies kann uns als Spielwiese dienen, um weiter in die Ursache-Wirkung von Tabellenpartitionierung, Datenverteilung und Abfragerouting einzutauchen.

Einzelserver-Tabellenpartitionierung

Single-Server-Partitionierung bedeutet einfach, dass sich alle Tabellenpartitionen auf demselben MySQL-Server/Instanz befinden. Beim Erstellen der Tabellenstruktur definieren wir alle Partitionen auf einmal. Diese Art der Partitionierung ist gut, wenn Sie Daten haben, die mit der Zeit an Nützlichkeit verlieren und leicht aus einer partitionierten Tabelle entfernt werden können, indem Sie die Partition (oder Partitionen) löschen, die nur diese Daten enthalten.

Erstellen Sie das Sysbench-Schema:

mysql> CREATE SCHEMA sbtest;

Erstellen Sie den Sysbench-Datenbankbenutzer:

mysql> CREATE USER 'sbtest'@'%' IDENTIFIED BY 'passw0rd';
mysql> GRANT ALL PRIVILEGES ON sbtest.* TO 'sbtest'@'%';

In Sysbench würde man den Befehl --prepare verwenden, um den MySQL-Server mit Schemastrukturen vorzubereiten und Datenzeilen zu generieren. Wir müssen diesen Teil überspringen und die Tabellenstruktur manuell definieren.

Erstellen Sie eine partitionierte Tabelle. In diesem Beispiel erstellen wir nur eine Tabelle namens sbtest1 und sie wird durch eine Spalte namens „k“ partitioniert, die im Grunde eine ganze Zahl zwischen 0 und 1.000.000 ist (basierend auf der Option --table-size, die wir haben später in der reinen Einfügeoperation verwenden):

mysql> CREATE TABLE `sbtest1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`,`k`)
  )
  PARTITION BY RANGE (k) (
    PARTITION p1 VALUES LESS THAN (499999),
    PARTITION p2 VALUES LESS THAN MAXVALUE
  );

Wir werden 2 Partitionen haben - Die erste Partition heißt p1 und speichert Daten, bei denen der Wert in Spalte "k" kleiner als 499.999 ist, und die zweite Partition, p2, speichert die restlichen Werte . Wir erstellen auch einen Primärschlüssel, der beide wichtigen Spalten enthält – „id“ steht für die Zeilenkennung und „k“ ist der Partitionsschlüssel. Bei der Partitionierung muss ein Primärschlüssel alle Spalten in der Partitionierungsfunktion der Tabelle enthalten (wobei wir „k“ in der Bereichspartitionierungsfunktion verwenden).

Vergewissern Sie sich, dass die Partitionen vorhanden sind:

mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS 
       FROM INFORMATION_SCHEMA.PARTITIONS 
       WHERE TABLE_SCHEMA='sbtest2' 
       AND TABLE_NAME='sbtest1';
+--------------+------------+----------------+------------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
+--------------+------------+----------------+------------+
| sbtest       | sbtest1    | p1             |          0 |
| sbtest       | sbtest1    | p2             |          0 |
+--------------+------------+----------------+------------+

Wir können dann eine reine Sysbench-Einfügeoperation wie folgt starten:

$ sysbench \
/usr/share/sysbench/oltp_insert.lua \
--report-interval=2 \
--threads=4 \
--rate=20 \
--time=9999 \
--db-driver=mysql \
--mysql-host=192.168.11.131 \
--mysql-port=3306 \
--mysql-user=sbtest \
--mysql-db=sbtest \
--mysql-password=passw0rd \
--tables=1 \
--table-size=1000000 \
run

Beobachten Sie, wie die Tabellenpartitionen wachsen, während Sysbench läuft:

mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS 
       FROM INFORMATION_SCHEMA.PARTITIONS 
       WHERE TABLE_SCHEMA='sbtest2' 
       AND TABLE_NAME='sbtest1';
+--------------+------------+----------------+------------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
+--------------+------------+----------------+------------+
| sbtest       | sbtest1    | p1             |       1021 |
| sbtest       | sbtest1    | p2             |       1644 |
+--------------+------------+----------------+------------+

Wenn wir die Gesamtzahl der Zeilen mit der COUNT-Funktion zählen, entspricht dies der Gesamtzahl der Zeilen, die von den Partitionen gemeldet werden:

mysql> SELECT COUNT(id) FROM sbtest1;
+-----------+
| count(id) |
+-----------+
|      2665 |
+-----------+

Das ist es. Wir haben eine Single-Server-Tabellenpartitionierung bereit, mit der wir herumspielen können.

Multi-Server-Tabellenpartitionierung

Bei Multi-Server-Partitionierung verwenden wir mehrere MySQL-Server, um eine Teilmenge von Daten einer bestimmten Tabelle (sbtest1) physisch zu speichern, wie im folgenden Diagramm gezeigt:

Wir werden zwei unabhängige MySQL-Knoten bereitstellen – mysql1 und mysql2. Die Tabelle sbtest1 wird auf diese beiden Knoten partitioniert, und wir nennen diese Kombination aus Partition und Host einen Shard. Sysbench wird remote auf dem dritten Server ausgeführt und ahmt die Anwendungsebene nach. Da Sysbench nicht partitionsfähig ist, benötigen wir einen Datenbanktreiber oder Router, um die Datenbankabfragen an den richtigen Shard weiterzuleiten. Wir werden ProxySQL verwenden, um diesen Zweck zu erreichen.

Lassen Sie uns zu diesem Zweck eine weitere neue Datenbank namens sbtest3 erstellen:

mysql> CREATE SCHEMA sbtest3;
mysql> USE sbtest3;

Gewähren Sie dem sbtest-Datenbankbenutzer die richtigen Berechtigungen:

mysql> CREATE USER 'sbtest'@'%' IDENTIFIED BY 'passw0rd';
mysql> GRANT ALL PRIVILEGES ON sbtest3.* TO 'sbtest'@'%';

Erstellen Sie auf mysql1 die erste Partition der Tabelle:

mysql> CREATE TABLE `sbtest1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`,`k`)
  )
  PARTITION BY RANGE (k) (
    PARTITION p1 VALUES LESS THAN (499999)
  );

Im Gegensatz zur Standalone-Partitionierung definieren wir nur die Bedingung für Partition p1 in der Tabelle, um alle Zeilen mit Werten der Spalte "k" zwischen 0 und 499.999 zu speichern.

Erstellen Sie auf mysql2 eine weitere partitionierte Tabelle:

mysql> CREATE TABLE `sbtest1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `k` int(11) NOT NULL DEFAULT '0',
  `c` char(120) NOT NULL DEFAULT '',
  `pad` char(60) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`,`k`)
  )
  PARTITION BY RANGE (k) (
    PARTITION p2 VALUES LESS THAN MAXVALUE
  );

Auf dem zweiten Server sollte er die Daten der zweiten Partition halten, indem er die restlichen erwarteten Werte der Spalte "k" speichert.

Unsere Tabellenstruktur kann jetzt mit Testdaten gefüllt werden.

Bevor wir den Sysbench-Einfügevorgang ausführen können, müssen wir einen ProxySQL-Server als Abfrage-Router installieren und als Gateway für unsere MySQL-Shards fungieren. Multi-Server-Sharding erfordert, dass Datenbankverbindungen, die von den Anwendungen kommen, zum richtigen Shard geleitet werden. Andernfalls würden Sie den folgenden Fehler sehen:

1526 (Table has no partition for value 503599)

Installieren Sie ProxySQL mit ClusterControl, fügen Sie den sbtest-Datenbankbenutzer zu ProxySQL hinzu, fügen Sie beide MySQL-Server zu ProxySQL hinzu und konfigurieren Sie mysql1 als Hostgruppe 11 und mysql2 als Hostgruppe 12:

Als Nächstes müssen wir daran arbeiten, wie die Abfrage weitergeleitet werden soll. Ein Beispiel für eine INSERT-Abfrage, die von Sysbench ausgeführt wird, sieht etwa so aus:

INSERT INTO sbtest1 (id, k, c, pad) 
  VALUES (0, 503502, '88816935247-23939908973-66486617366-05744537902-39238746973-63226063145-55370375476-52424898049-93208870738-99260097520', '36669559817-75903498871-26800752374-15613997245-76119597989')

Wir werden also den folgenden regulären Ausdruck verwenden, um die INSERT-Abfrage nach „k“ => 500000 zu filtern, um die Partitionierungsbedingung zu erfüllen:

^INSERT INTO sbtest1 \(id, k, c, pad\) VALUES \([0-9]\d*, ([5-9]{1,}[0-9]{5}|[1-9]{1,}[0-9]{6,}).*

Der obige Ausdruck versucht einfach Folgendes zu filtern:

  • [0-9]\d* - Wir erwarten hier eine Autoinkrement-Ganzzahl, daher gleichen wir jede Ganzzahl ab.

  • [5-9]{1,}[0-9]{5} - Der Wert stimmt mit einer beliebigen Ganzzahl von 5 als erste Ziffer und 0-9 auf den letzten 5 Ziffern überein, um mit dem Bereichswert von 500.000 bis 999.999 übereinzustimmen.

  • [1-9]{1,}[0-9]{6,} - Der Wert stimmt mit jeder ganzen Zahl von 1 bis 9 als erste Ziffer und 0 bis 9 auf den letzten 6 oder größeren Ziffern überein, um mit dem Wert von 1.000.000 und größer übereinzustimmen.

Wir werden zwei ähnliche Abfrageregeln erstellen. Die erste Abfrageregel ist die Negation des obigen regulären Ausdrucks. Wir geben dieser Regel-ID 51 und die Ziel-Hostgruppe sollte Hostgruppe 11 sein, um mit Spalte „k“ <500.000 übereinzustimmen und die Abfragen an die erste Partition weiterzuleiten. Es sollte so aussehen:

Achten Sie auf das „Negate Match Pattern“ im obigen Screenshot. Diese Option ist entscheidend für das richtige Routing dieser Abfrageregel.

Erstellen Sie als Nächstes eine weitere Abfrageregel mit der Regel-ID 52, verwenden Sie denselben regulären Ausdruck, und die Ziel-Hostgruppe sollte 12 sein, aber dieses Mal lassen Sie das "Negate Match Pattern" auf "false", wie unten gezeigt:

Wir können dann mit Sysbench einen reinen Einfügevorgang starten, um Testdaten zu generieren . Die auf den MySQL-Zugriff bezogenen Informationen sollten der ProxySQL-Host (192.168.11.130 auf Port 6033) sein:

$ sysbench \
/usr/share/sysbench/oltp_insert.lua \
--report-interval=2 \
--threads=4 \
--rate=20 \
--time=9999 \
--db-driver=mysql \
--mysql-host=192.168.11.130 \
--mysql-port=6033 \
--mysql-user=sbtest \
--mysql-db=sbtest3 \
--mysql-password=passw0rd \
--tables=1 \
--table-size=1000000 \
run

Wenn Sie keinen Fehler sehen, bedeutet dies, dass ProxySQL unsere Abfragen an den richtigen Shard/die richtige Partition weitergeleitet hat. Sie sollten sehen, dass die Abfrageregeltreffer zunehmen, während der Sysbench-Prozess ausgeführt wird:

Unter dem Abschnitt Top Queries sehen wir die Zusammenfassung des Query-Routings:

Um dies zu überprüfen, melden Sie sich bei mysql1 an, suchen Sie nach der ersten Partition und überprüfen Sie den Mindest- und Höchstwert der Spalte „k“ in Tabelle sbtest1:

mysql> USE sbtest3;
mysql> SELECT min(k), max(k) FROM sbtest1;
+--------+--------+
| min(k) | max(k) |
+--------+--------+
| 232185 | 499998 |
+--------+--------+

Sieht toll aus. Der Maximalwert der Spalte "k" überschreitet nicht die Grenze von 499.999. Lassen Sie uns die Anzahl der Zeilen überprüfen, die für diese Partition gespeichert werden:

mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS 
       FROM INFORMATION_SCHEMA.PARTITIONS 
       WHERE TABLE_SCHEMA='sbtest3' 
       AND TABLE_NAME='sbtest1';
+--------------+------------+----------------+------------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
+--------------+------------+----------------+------------+
| sbtest3      | sbtest1    | p1             |       1815 |
+--------------+------------+----------------+------------+

Lassen Sie uns nun den anderen MySQL-Server (mysql2) überprüfen:

mysql> USE sbtest3;
mysql> SELECT min(k), max(k) FROM sbtest1;
+--------+--------+
| min(k) | max(k) |
+--------+--------+
| 500003 | 794952 |
+--------+--------+

Überprüfen wir die Anzahl der Zeilen, die für diese Partition gespeichert werden:

mysql> SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, TABLE_ROWS 
       FROM INFORMATION_SCHEMA.PARTITIONS 
       WHERE TABLE_SCHEMA='sbtest3' 
       AND TABLE_NAME='sbtest1';
+--------------+------------+----------------+------------+
| TABLE_SCHEMA | TABLE_NAME | PARTITION_NAME | TABLE_ROWS |
+--------------+------------+----------------+------------+
| sbtest3      | sbtest1    | p2             |       3247 |
+--------------+------------+----------------+------------+

Hervorragend! Wir haben ein fragmentiertes MySQL-Testsetup mit richtiger Datenpartitionierung mit Sysbench, mit dem wir herumspielen können. Viel Spaß beim Benchmarking!