sql >> Database teknologi >  >> RDS >> MariaDB

Brug af Sysbench til at generere testdata til Sharded Table i MySQL

Sysbench er et fantastisk værktøj til at generere testdata og udføre MySQL OLTP-benchmarks. Normalt ville man lave en forberedelse-kør-oprydningscyklus, når man udfører benchmark ved hjælp af Sysbench. Som standard er tabellen genereret af Sysbench en standard ikke-partitionsbasistabel. Denne adfærd kan selvfølgelig udvides, men du skal vide, hvordan du skriver den i LUA-scriptet.

I dette blogindlæg skal vi vise, hvordan man genererer testdata til en opdelt tabel i MySQL ved hjælp af Sysbench. Dette kan bruges som en legeplads for os til at dykke længere ned i årsag-virkningen af ​​tabelopdeling, datadistribution og forespørgselsrouting.

Enkeltserver-tabelpartitionering

Enkeltserver-partitionering betyder ganske enkelt, at alle tabellens partitioner ligger på den samme MySQL-server/instans. Når vi opretter tabelstrukturen, definerer vi alle partitionerne på én gang. Denne form for partitionering er god, hvis du har data, der mister deres anvendelighed over tid og nemt kan fjernes fra en partitioneret tabel ved at droppe den partition (eller partitioner), der kun indeholder disse data.

Opret Sysbench-skemaet:

mysql> CREATE SCHEMA sbtest; 

Opret sysbench-databasebrugeren:

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

I Sysbench ville man bruge kommandoen --prepare til at forberede MySQL-serveren med skemastrukturer og generere rækker af data. Vi er nødt til at springe denne del over og definere tabelstrukturen manuelt.

Opret en opdelt tabel. I dette eksempel vil vi kun oprette én tabel kaldet sbtest1, og den vil blive opdelt af en kolonne med navnet "k", som grundlæggende er et heltal med intervaller mellem 0 og 1.000.000 (baseret på --table-size-indstillingen, som vi er skal bruges i indsættelses-kun-operationen senere):

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
  ); 

Vi kommer til at have 2 partitioner - Den første partition kaldes p1 og vil gemme data, hvor værdien i kolonne "k" er lavere end 499.999, og den anden partition, p2, vil gemme de resterende værdier . Vi opretter også en primær nøgle, der indeholder begge vigtige kolonner - "id" er for rækkeidentifikator og "k" er partitionsnøglen. Ved partitionering skal en primær nøgle inkludere alle kolonner i tabellens partitioneringsfunktion (hvor vi bruger "k" i områdepartitionsfunktionen).

Bekræft at partitionerne er der:

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 |
+--------------+------------+----------------+------------+ 

Vi kan derefter starte en Sysbench-indsætningsoperation som nedenfor:

$ 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 

Se tabelpartitionerne vokse, mens Sysbench kører:

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 |
+--------------+------------+----------------+------------+ 

Hvis vi tæller det samlede antal rækker ved hjælp af COUNT-funktionen, vil det svare til det samlede antal rækker rapporteret af partitionerne:

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

Det var det. Vi har en enkelt-server bordpartitionering klar, som vi kan lege med.

Multi-server tabelpartitionering

I multi-server partitionering vil vi bruge flere MySQL-servere til fysisk at gemme en delmængde af data i en bestemt tabel (sbtest1), som vist i følgende diagram:

Vi skal installere 2 uafhængige MySQL-noder - mysql1 og mysql2. sbtest1-tabellen vil blive partitioneret på disse to noder, og vi vil kalde denne partition + værtskombination for et shard. Sysbench kører eksternt på den tredje server og efterligner applikationsniveauet. Da Sysbench ikke er partitionsbevidst, skal vi have en databasedriver eller router for at dirigere databaseforespørgslerne til det rigtige shard. Vi vil bruge ProxySQL til at opnå dette formål.

Lad os oprette endnu en ny database kaldet sbtest3 til dette formål:

mysql> CREATE SCHEMA sbtest3;
mysql> USE sbtest3; 

Giv de rigtige privilegier til sbtest-databasebrugeren:

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

På mysql1 skal du oprette den første partition i tabellen:

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)
  ); 

I modsætning til selvstændig partitionering definerer vi kun betingelsen for partition p1 i tabellen for at gemme alle rækker med kolonne "k"-værdier fra 0 til 499.999.

Opret en anden partitioneret tabel på mysql2:

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
  ); 

På den anden server skal den indeholde dataene fra den anden partition ved at gemme de resterende af de forventede værdier i kolonne "k".

Vores tabelstruktur er nu klar til at blive udfyldt med testdata.

Før vi kan køre Sysbench-indsættelsesoperationen, skal vi installere en ProxySQL-server som forespørgselsrouter og fungere som gateway for vores MySQL-shards. Multi-server sharding kræver, at databaseforbindelser, der kommer fra applikationerne, dirigeres til det korrekte shard. Ellers vil du se følgende fejl:

1526 (Table has no partition for value 503599) 

Installer ProxySQL ved hjælp af ClusterControl, tilføj sbtest-databasebrugeren til ProxySQL, tilføj begge MySQL-servere til ProxySQL og konfigurer mysql1 som værtsgruppe 11 og mysql2 som værtsgruppe 12:

Dernæst skal vi arbejde på, hvordan forespørgslen skal dirigeres. Et eksempel på INSERT-forespørgslen, der udføres af Sysbench, vil se nogenlunde sådan ud:

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') 

Så vi vil bruge følgende regulære udtryk til at filtrere INSERT-forespørgslen efter "k" => 500000, for at opfylde partitioneringsbetingelsen:

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

Ovenstående udtryk forsøger blot at filtrere følgende:

  • [0-9]\d* - Vi forventer et auto-increment heltal her, så vi matcher med ethvert heltal.

  • [5-9]{1,}[0-9]{5} - Værdien matcher ethvert heltal fra 5 som det første ciffer og 0-9 på de sidste 5 cifre for at matche intervalværdien fra 500.000 til 999.999.

  • [1-9]{1,}[0-9]{6,} - Værdien matcher ethvert heltal fra 1-9 som det første ciffer og 0-9 på de sidste 6 eller større cifre for at matche værdien fra 1.000.000 og derover.

Vi vil oprette to lignende forespørgselsregler. Den første forespørgselsregel er negationen af ​​ovenstående regulære udtryk. Vi giver denne regel ID 51, og destinationsværtsgruppen skal være værtsgruppe 11 for at matche kolonne "k" <500.000 og videresende forespørgslerne til den første partition. Det skulle se sådan ud:

Vær opmærksom på "Negate Match Pattern" i ovenstående skærmbillede. Denne mulighed er afgørende for den korrekte routing af denne forespørgselsregel.

Opret dernæst en anden forespørgselsregel med regel-id 52 ved at bruge det samme regulære udtryk, og destinationsværtsgruppen skal være 12, men denne gang skal du lade "Negate Match Pattern" være falsk, som vist nedenfor:

Vi kan derefter starte en indsættelsesoperation ved at bruge Sysbench til at generere testdata . De MySQL-adgangsrelaterede oplysninger skal være ProxySQL-værten (192.168.11.130 på port 6033):

$ 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 

Hvis du ikke ser nogen fejl, betyder det, at ProxySQL har dirigeret vores forespørgsler til den korrekte shard/partition. Du bør se, at forespørgselsregelhits stiger, mens Sysbench-processen kører:

Under sektionen Topforespørgsler kan vi se oversigten over forespørgselsrutingen:

For at dobbelttjekke skal du logge ind på mysql1 for at lede efter den første partition og kontrollere minimum- og maksimumværdien af ​​kolonne 'k' i tabel sbtest1:

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

Ser godt ud. Den maksimale værdi af kolonne "k" overstiger ikke grænsen på 499.999. Lad os tjekke antallet af rækker, den gemmer for denne partition:

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 |
+--------------+------------+----------------+------------+ 

Lad os nu tjekke den anden MySQL-server (mysql2):

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

Lad os tjekke antallet af rækker, den gemmer for denne partition:

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 |
+--------------+------------+----------------+------------+ 

Fantastisk! Vi har en shard MySQL-testopsætning med korrekt datapartitionering ved hjælp af Sysbench, som vi kan lege med. God benchmarking!


  1. .NET / Oracle:Sådan udføres et script med DDL-sætninger programmatisk

  2. Top tre tendenser, der påvirker DBA'er Ansvarlig for SQL Server-overvågning

  3. Hvordan kan jeg afkorte en datetime i SQL Server?

  4. Hvordan udfører man en SQLite-forespørgsel i en Android-applikation?