Sysbench är ett utmärkt verktyg för att generera testdata och utföra MySQL OLTP-riktmärken. Vanligtvis skulle man göra en förberedelse-kör-rensningscykel när man utför benchmark med Sysbench. Som standard är tabellen som genereras av Sysbench en standard icke-partitionsbastabell. Detta beteende kan naturligtvis utökas, men du måste veta hur man skriver det i LUA-skriptet.
I det här blogginlägget kommer vi att visa hur man genererar testdata för en partitionerad tabell i MySQL med Sysbench. Detta kan användas som en lekplats för oss att dyka längre in i orsak-effekten av tabellpartitionering, datadistribution och frågedirigering.
Enkelserver-tabellpartitionering
Enkelserverpartitionering betyder helt enkelt att alla tabellpartitioner finns på samma MySQL-server/instans. När vi skapar tabellstrukturen kommer vi att definiera alla partitioner på en gång. Den här typen av partitionering är bra om du har data som förlorar sin användbarhet med tiden och som enkelt kan tas bort från en partitionerad tabell genom att ta bort partitionen (eller partitionerna) som bara innehåller dessa data.
Skapa Sysbench-schemat:
mysql> CREATE SCHEMA sbtest;
Skapa sysbench-databasanvändaren:
mysql> CREATE USER 'sbtest'@'%' IDENTIFIED BY 'passw0rd';
mysql> GRANT ALL PRIVILEGES ON sbtest.* TO 'sbtest'@'%';
I Sysbench skulle man använda kommandot --prepare för att förbereda MySQL-servern med schemastrukturer och generera rader med data. Vi måste hoppa över den här delen och definiera tabellstrukturen manuellt.
Skapa en partitionerad tabell. I det här exemplet kommer vi bara att skapa en tabell som heter sbtest1 och den kommer att partitioneras av en kolumn som heter "k", vilket i grunden är ett heltal mellan 0 och 1 000 000 (baserat på --table-size-alternativet som vi är kommer att användas i operationen endast infogning senare):
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 att ha 2 partitioner - Den första partitionen kallas p1 och kommer att lagra data där värdet i kolumn "k" är lägre än 499 999 och den andra partitionen, p2, kommer att lagra de återstående värdena . Vi skapar också en primärnyckel som innehåller båda viktiga kolumnerna - "id" är för radidentifierare och "k" är partitionsnyckeln. Vid partitionering måste en primärnyckel inkludera alla kolumner i tabellens partitioneringsfunktion (där vi använder "k" i intervallpartitionsfunktionen).
Verifiera att partitionerna finns där:
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 sedan starta en Sysbench-insättningsoperation enligt nedan:
$ 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 tabellpartitionerna växa när Sysbench körs:
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 |
+--------------+------------+----------------+------------+
Om vi räknar det totala antalet rader med COUNT-funktionen kommer det att motsvara det totala antalet rader som rapporteras av partitionerna:
mysql> SELECT COUNT(id) FROM sbtest1;
+-----------+
| count(id) |
+-----------+
| 2665 |
+-----------+
Det var allt. Vi har en tabellpartitionering med en server redo som vi kan leka med.
Tabellpartitionering med flera servrar
I partitionering med flera servrar kommer vi att använda flera MySQL-servrar för att fysiskt lagra en delmängd av data i en viss tabell (sbtest1), som visas i följande diagram:
Vi kommer att distribuera 2 oberoende MySQL-noder - mysql1 och mysql2. Tabellen sbtest1 kommer att partitioneras på dessa två noder och vi kallar denna partition + värdkombination för en shard. Sysbench körs på distans på den tredje servern och härmar applikationsnivån. Eftersom Sysbench inte är partitionsmedveten måste vi ha en databasdrivrutin eller router för att dirigera databasfrågorna till rätt skärva. Vi kommer att använda ProxySQL för att uppnå detta syfte.
Låt oss skapa ytterligare en ny databas som heter sbtest3 för detta ändamål:
mysql> CREATE SCHEMA sbtest3;
mysql> USE sbtest3;
Ge rätt behörigheter till sbtest-databasanvändaren:
mysql> CREATE USER 'sbtest'@'%' IDENTIFIED BY 'passw0rd';
mysql> GRANT ALL PRIVILEGES ON sbtest3.* TO 'sbtest'@'%';
På mysql1, skapa den första partitionen 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)
);
Till skillnad från fristående partitionering, definierar vi bara villkoret för partition p1 i tabellen för att lagra alla rader med kolumn "k"-värden som sträcker sig från 0 till 499 999.
På mysql2, skapa en annan partitionerad tabell:
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 andra servern bör den innehålla data från den andra partitionen genom att lagra återstående av de förväntade värdena i kolumn "k".
Vår tabellstruktur är nu redo att fyllas i med testdata.
Innan vi kan köra Sysbench insert-only operation måste vi installera en ProxySQL-server som frågerouter och fungera som gateway för våra MySQL-skärvor. Skärning av flera servrar kräver att databasanslutningar som kommer från applikationerna dirigeras till rätt fragment. Annars skulle du se följande fel:
1526 (Table has no partition for value 503599)
Installera ProxySQL med ClusterControl, lägg till sbtest-databasanvändaren i ProxySQL, lägg till båda MySQL-servrarna i ProxySQL och konfigurera mysql1 som värdgrupp 11 och mysql2 som värdgrupp 12:
Närnäst måste vi arbeta med hur frågan ska dirigeras. Ett exempel på INSERT-frågan som kommer att utföras av Sysbench kommer att se ut ungefär så här:
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 kommer att använda följande reguljära uttryck för att filtrera INSERT-frågan för "k" => 500000, för att uppfylla partitioneringsvillkoret:
^INSERT INTO sbtest1 \(id, k, c, pad\) VALUES \([0-9]\d*, ([5-9]{1,}[0-9]{5}|[1-9]{1,}[0-9]{6,}).*
Ovanstående uttryck försöker helt enkelt filtrera följande:
-
[0-9]\d* - Vi förväntar oss ett heltal med automatisk ökning här, så vi matchar mot vilket heltal som helst.
-
[5-9]{1,}[0-9]{5} - Värdet matchar alla heltal från 5 som första siffra och 0-9 på de sista 5 siffrorna, för att matcha intervallvärdet från 500 000 till 999 999.
-
[1-9]{1,}[0-9]{6,} - Värdet matchar alla heltal från 1-9 som första siffra och 0-9 på de sista 6 eller större siffrorna, för att matcha värdet från 1 000 000 och större.
Vi kommer att skapa två liknande frågeregler. Den första frågeregeln är negationen av ovanstående reguljära uttryck. Vi ger denna regel ID 51 och destinationsvärdgruppen ska vara värdgrupp 11 för att matcha kolumn "k" <500 000 och vidarebefordra frågorna till den första partitionen. Det ska se ut så här:
Var uppmärksam på "Negate Match Pattern" i skärmdumpen ovan. Det alternativet är avgörande för korrekt dirigering av den här frågeregeln.
Skapa sedan en annan frågeregel med regel-ID 52, med samma reguljära uttryck och destinationsvärdgruppen ska vara 12, men den här gången lämnar du "Negate Match Pattern" som falskt, som visas nedan:
Vi kan sedan starta en insättningsoperation med Sysbench för att generera testdata . Den MySQL-åtkomstrelaterade informationen bör vara ProxySQL-värden (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
Om du inte ser något fel betyder det att ProxySQL har dirigerat våra frågor till rätt fragment/partition. Du bör se att sökregelträffarna ökar medan Sysbench-processen körs:
Under avsnittet Top Queries kan vi se sammanfattningen av frågedirigeringen:
För att dubbelkolla, logga in på mysql1 för att leta efter den första partitionen och kontrollera det lägsta och högsta värdet för kolumn 'k' i tabellen sbtest1:
mysql> USE sbtest3;
mysql> SELECT min(k), max(k) FROM sbtest1;
+--------+--------+
| min(k) | max(k) |
+--------+--------+
| 232185 | 499998 |
+--------+--------+
Ser bra ut. Det maximala värdet för kolumn "k" överstiger inte gränsen på 499 999. Låt oss kontrollera antalet rader den lagrar för denna 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 |
+--------------+------------+----------------+------------+
Låt oss nu kolla den andra MySQL-servern (mysql2):
mysql> USE sbtest3;
mysql> SELECT min(k), max(k) FROM sbtest1;
+--------+--------+
| min(k) | max(k) |
+--------+--------+
| 500003 | 794952 |
+--------+--------+
Låt oss kontrollera antalet rader den lagrar för den här partitionen:
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 |
+--------------+------------+----------------+------------+
Utmärkt! Vi har en delad MySQL-testinstallation med korrekt datapartitionering med Sysbench som vi kan leka med. Lycka till med benchmarking!