Co to jest SysBench? Jeśli regularnie pracujesz z MySQL, to najprawdopodobniej słyszałeś o nim. SysBench od dawna jest obecny w ekosystemie MySQL. Został napisany przez Petera Zaitseva w 2004 roku. Jego celem było dostarczenie narzędzia do uruchamiania syntetycznych testów porównawczych MySQL i sprzętu, na którym działa. Został zaprojektowany do przeprowadzania testów procesora, pamięci i I/O. Miał również możliwość wykonania obciążenia OLTP na bazie danych MySQL. OLTP oznacza przetwarzanie transakcji online, typowe obciążenie dla aplikacji internetowych, takich jak handel elektroniczny, wprowadzanie zamówień lub systemy transakcji finansowych.
W tym poście skupimy się na funkcji testu porównawczego SQL, ale pamiętaj, że testy sprzętowe mogą być również bardzo przydatne w identyfikowaniu problemów na serwerach baz danych. Na przykład benchmark I/O miał na celu symulację obciążenia I/O InnoDB, podczas gdy testy procesora obejmują symulację wysoce współbieżnego, wielowątkowego środowiska wraz z testami rywalizacji mutex – coś, co również przypomina obciążenie bazy danych.
Historia i architektura SysBench
Jak wspomniano, SysBench został pierwotnie stworzony w 2004 roku przez Petera Zaitseva. Wkrótce jego rozwój przejął Aleksiej Kopytow. Osiągnął wersję 0.4.12 i rozwój został wstrzymany. Po długiej przerwie Alexey ponownie rozpoczął pracę nad SysBench w 2016 roku. Wkrótce została wydana wersja 0.5 z przepisanym benchmarkiem OLTP, aby używać skryptów opartych na LUA. Następnie, w 2017 roku, wydano SysBench 1.0. To było jak dzień i noc w porównaniu do starej wersji 0.4.12. Przede wszystkim, zamiast zakodowanych na sztywno skryptów, mamy teraz możliwość dostosowywania benchmarków za pomocą LUA. Na przykład Percona stworzyła benchmark podobny do TPCC, który można wykonać za pomocą SysBench. Rzućmy okiem na obecną architekturę SysBench.
SysBench to plik binarny C, który używa skryptów LUA do wykonywania testów porównawczych. Te skrypty muszą:
- Obsługuj dane wejściowe z parametrów wiersza poleceń
- Zdefiniuj wszystkie tryby, których ma używać benchmark (przygotowanie, uruchomienie, czyszczenie)
- Przygotuj wszystkie dane
- Zdefiniuj sposób wykonania testu porównawczego (jak będą wyglądały zapytania itp.)
Skrypty mogą wykorzystywać wiele połączeń z bazą danych, mogą również przetwarzać wyniki, jeśli chcesz tworzyć złożone testy porównawcze, w których zapytania zależą od zestawu wyników poprzednich zapytań. Dzięki SysBench 1.0 możliwe jest tworzenie histogramów opóźnień. Możliwe jest również, że skrypty LUA wychwytują i obsługują błędy za pomocą haków błędów. W skryptach LUA jest wsparcie dla paralelizacji, wiele zapytań może być wykonywanych równolegle, dzięki czemu na przykład aprowizacja jest znacznie szybsza. Co nie mniej ważne, obsługiwanych jest teraz wiele formatów wyjściowych. Wcześniej SysBench generował tylko dane wyjściowe czytelne dla człowieka. Teraz możliwe jest generowanie go jako CSV lub JSON, co znacznie ułatwia przetwarzanie końcowe i generowanie wykresów za pomocą na przykład gnuplot lub przesyłanie danych do Prometheus, Graphite lub podobnego magazynu danych.
Dlaczego SysBench?
Głównym powodem, dla którego SysBench stał się popularny, jest fakt, że jest prosty w użyciu. Ktoś bez wcześniejszej wiedzy może zacząć z niego korzystać w ciągu kilku minut. Zapewnia również domyślnie testy porównawcze, które obejmują większość przypadków — obciążenia OLTP, tylko do odczytu lub do odczytu i zapisu, wyszukiwania kluczy podstawowych i aktualizacje kluczy podstawowych. Wszystko to spowodowało większość problemów z MySQL, aż do MySQL 8.0. Był to również powód, dla którego SysBench był tak popularny w różnych benchmarkach i porównaniach publikowanych w Internecie. Te posty pomogły wypromować to narzędzie i stały się syntetycznym testem porównawczym dla MySQL.
Kolejną dobrą rzeczą w SysBench jest to, że od wersji 0.5 i włączenia LUA każdy może przygotować dowolny benchmark. Wspomnieliśmy już o benchmarku podobnym do TPCC, ale każdy może stworzyć coś, co będzie przypominało jej obciążenie produkcyjne. Nie mówimy, że jest to proste, najprawdopodobniej będzie to czasochłonny proces, ale posiadanie tej umiejętności jest korzystne, jeśli musisz przygotować niestandardowy test porównawczy.
Będąc syntetycznym testem porównawczym, SysBench nie jest narzędziem, którego można użyć do dostrojenia konfiguracji serwerów MySQL (chyba że przygotowałeś skrypty LUA z niestandardowym obciążeniem lub Twoje obciążenie jest bardzo podobne do obciążeń testowych dostarczanych przez SysBench). To, do czego jest świetne, to porównywanie wydajności różnych urządzeń. Możesz łatwo porównać wydajność, powiedzmy, różnych typów węzłów oferowanych przez dostawcę chmury i maksymalną liczbę QPS (zapytań na sekundę), którą oferuje. Znając tę metrykę i wiedząc, ile płacisz za dany węzeł, możesz obliczyć jeszcze ważniejszą metrykę - QP$ (zapytania za dolara). Umożliwi to określenie typu węzła, którego należy użyć podczas budowania efektywnego kosztowo środowiska. Oczywiście SysBench można wykorzystać również do wstępnego dostrojenia i oceny wykonalności danego projektu. Załóżmy, że budujemy klaster Galera obejmujący cały świat – Amerykę Północną, UE, Azję. Ile wkładek na sekundę może obsłużyć taka konfiguracja? Jaki byłby czas oczekiwania na zatwierdzenie? Czy w ogóle ma sens przeprowadzanie dowodu koncepcji, czy może opóźnienie sieci jest na tyle duże, że nawet proste obciążenie nie działa zgodnie z oczekiwaniami.
A co z testami warunków skrajnych? Nie wszyscy przenieśli się do chmury, wciąż są firmy, które wolą budować własną infrastrukturę. Każdy nowy zakupiony serwer powinien przejść przez okres rozgrzewania, podczas którego będziesz go obciążać, aby zidentyfikować potencjalne wady sprzętu. W tym przypadku SysBench również może pomóc. Albo wykonując obciążenie OLTP, które przeciąża serwer, albo możesz również użyć dedykowanych testów porównawczych dla procesora, dysku i pamięci.
Jak widać, jest wiele przypadków, w których nawet prosty, syntetyczny benchmark może być bardzo przydatny. W następnym akapicie przyjrzymy się, co możemy zrobić z SysBench.
Co SysBench może dla Ciebie zrobić?
Jakie testy możesz przeprowadzić?
Jak wspomniano na początku, skupimy się na benchmarkach OLTP i dla przypomnienia powtórzymy, że SysBench może być również używany do przeprowadzania testów I/O, procesora i pamięci. Przyjrzyjmy się testom porównawczym, które dostarcza SysBench 1.0 (usunęliśmy z tej listy niektóre pomocnicze pliki LUA i niebazowe skrypty LUA).
-rwxr-xr-x 1 root root 1.5K May 30 07:46 bulk_insert.lua
-rwxr-xr-x 1 root root 1.3K May 30 07:46 oltp_delete.lua
-rwxr-xr-x 1 root root 2.4K May 30 07:46 oltp_insert.lua
-rwxr-xr-x 1 root root 1.3K May 30 07:46 oltp_point_select.lua
-rwxr-xr-x 1 root root 1.7K May 30 07:46 oltp_read_only.lua
-rwxr-xr-x 1 root root 1.8K May 30 07:46 oltp_read_write.lua
-rwxr-xr-x 1 root root 1.1K May 30 07:46 oltp_update_index.lua
-rwxr-xr-x 1 root root 1.2K May 30 07:46 oltp_update_non_index.lua
-rwxr-xr-x 1 root root 1.5K May 30 07:46 oltp_write_only.lua
-rwxr-xr-x 1 root root 1.9K May 30 07:46 select_random_points.lua
-rwxr-xr-x 1 root root 2.1K May 30 07:46 select_random_ranges.lua
Przeanalizujmy je jeden po drugim.
Najpierw bulk_insert.lua. Ten test może być użyty do porównania zdolności MySQL do wykonywania wielowierszowych wstawek. Może to być bardzo przydatne podczas sprawdzania np. wydajności replikacji lub klastra Galera. W pierwszym przypadku może pomóc odpowiedzieć na pytanie:„jak szybko mogę wstawić, zanim rozpocznie się opóźnienie replikacji?”. W drugim przypadku powie Ci, jak szybko dane można wstawić do klastra Galera, biorąc pod uwagę obecne opóźnienie sieci.
Wszystkie skrypty oltp_* mają wspólną strukturę tabeli. Pierwsze dwa z nich (oltp_delete.lua i oltp_insert.lua) wykonują pojedyncze instrukcje DELETE i INSERT. Ponownie, może to być test dla replikacji lub klastra Galera — przesuń go do granic możliwości i zobacz, jaka ilość wstawiania lub czyszczenia może obsłużyć. Mamy również inne testy porównawcze skoncentrowane na konkretnej funkcjonalności - oltp_point_select, oltp_update_index i oltp_update_non_index. Wykonają one podzbiór zapytań — wybory oparte na kluczu podstawowym, aktualizacje oparte na indeksie i aktualizacje nieoparte na indeksie. Jeśli chcesz przetestować niektóre z tych funkcji, testy są dostępne. Mamy również bardziej złożone testy porównawcze oparte na obciążeniach OLTP:oltp_read_only, oltp_read_write i oltp_write_only. Możesz uruchomić obciążenie tylko do odczytu, które będzie składało się z różnych typów zapytań SELECT, możesz uruchamiać tylko zapisy (mieszanka DELETE, INSERT i UPDATE) lub możesz uruchomić mieszankę tych dwóch. Na koniec, używając select_random_points i select_random_ranges, możesz uruchomić losowy SELECT albo używając losowych punktów z listy IN(), albo losowych zakresów używając BETWEEN.
Jak skonfigurować test porównawczy?
Co ważne, benchmarki są konfigurowalne – możesz uruchamiać różne wzorce obciążenia przy użyciu tego samego benchmarku. Przyjrzyjmy się dwóm najczęstszym testom porównawczym do wykonania. Zagłębimy się w testy porównawcze OLTP read_only i OLTP read_write. Przede wszystkim SysBench ma kilka ogólnych opcji konfiguracyjnych. Omówimy tutaj tylko te najważniejsze, możesz je wszystkie sprawdzić, uruchamiając:
sysbench --help
Przyjrzyjmy się im.
--threads=N number of threads to use [1]
Możesz określić, jaki rodzaj współbieżności ma wygenerować SysBench. MySQL, jak każde oprogramowanie, ma pewne ograniczenia skalowalności, a jego wydajność osiągnie szczyt na pewnym poziomie współbieżności. To ustawienie pomaga zasymulować różne współbieżności dla danego obciążenia i sprawdzić, czy przekroczyło ono już optymalny punkt.
--events=N limit for total number of events [0]
--time=N limit for total execution time in seconds [10]
Te dwa ustawienia określają, jak długo SysBench powinien działać. Może wykonać pewną liczbę zapytań lub może działać przez określony czas.
--warmup-time=N execute events for this many seconds with statistics disabled before the actual benchmark run with statistics enabled [0]
To nie wymaga wyjaśnień. SysBench generuje wyniki statystyczne z testów, na które może mieć wpływ zimny stan MySQL. Warmup pomaga zidentyfikować „zwykłą” przepustowość, wykonując test porównawczy przez wstępnie zdefiniowany czas, pozwalając na rozgrzanie pamięci podręcznej, pul buforów itp.
--rate=N average transactions rate. 0 for unlimited rate [0]
Domyślnie SysBench będzie próbował wykonać zapytania tak szybko, jak to możliwe. Do symulacji wolniejszego ruchu można użyć tej opcji. Tutaj możesz zdefiniować, ile transakcji ma być wykonywanych na sekundę.
--report-interval=N periodically report intermediate statistics with a specified interval in seconds. 0 disables intermediate reports [0]
Domyślnie SysBench generuje raport po zakończeniu swojego działania i podczas działania testu porównawczego nie jest raportowany żaden postęp. Korzystając z tej opcji, możesz uczynić SysBench bardziej gadatliwym, gdy test porównawczy nadal działa.
--rand-type=STRING random numbers distribution {uniform, gaussian, special, pareto, zipfian} to use by default [special]
SysBench daje możliwość generowania różnych rodzajów dystrybucji danych. Wszystkie mogą mieć swoje własne cele. Domyślna opcja „specjalna” definiuje kilka (można je konfigurować) hot-spotów w danych, co jest dość powszechne w aplikacjach internetowych. Możesz również użyć innych dystrybucji, jeśli Twoje dane zachowują się w inny sposób. Dokonując tutaj innego wyboru, możesz również zmienić sposób obciążania bazy danych. Na przykład równomierna dystrybucja, w której wszystkie wiersze mają takie samo prawdopodobieństwo uzyskania dostępu, jest operacją znacznie bardziej intensywnie wykorzystującą pamięć. Wykorzysta więcej puli buforów do przechowywania wszystkich danych i będzie znacznie bardziej intensywnie wykorzystywać dysk, jeśli zestaw danych nie zmieści się w pamięci. Z drugiej strony, specjalna dystrybucja z kilkoma punktami aktywnymi zmniejszy obciążenie dysku, ponieważ gorące wiersze będą częściej przechowywane w puli buforów, a dostęp do wierszy przechowywanych na dysku jest znacznie mniej prawdopodobny. W przypadku niektórych typów dystrybucji danych SysBench zapewnia więcej poprawek. Możesz znaleźć te informacje w wyniku „sysbench --help”.
--db-ps-mode=STRING prepared statements usage mode {auto, disable} [auto]
Korzystając z tego ustawienia możesz zdecydować, czy SysBench ma używać przygotowanych instrukcji (o ile są one dostępne w danym magazynie danych - dla MySQL oznacza to, że PS będzie domyślnie włączone), czy nie. Może to mieć znaczenie podczas pracy z proxy, takimi jak ProxySQL lub MaxScale - powinny one traktować przygotowane instrukcje w specjalny sposób i wszystkie powinny być kierowane do jednego hosta, co uniemożliwia testowanie skalowalności proxy.
Oprócz ogólnych opcji konfiguracyjnych każdy z testów może mieć własną konfigurację. Możesz sprawdzić, co jest możliwe, uruchamiając:
[email protected]:~# sysbench ./sysbench/src/lua/oltp_read_write.lua help
sysbench 1.1.0-2e6b7d5 (using bundled LuaJIT 2.1.0-beta3)
oltp_read_only.lua options:
--distinct_ranges=N Number of SELECT DISTINCT queries per transaction [1]
--sum_ranges=N Number of SELECT SUM() queries per transaction [1]
--skip_trx[=on|off] Don't start explicit transactions and execute all queries in the AUTOCOMMIT mode [off]
--secondary[=on|off] Use a secondary index in place of the PRIMARY KEY [off]
--create_secondary[=on|off] Create a secondary index in addition to the PRIMARY KEY [on]
--index_updates=N Number of UPDATE index queries per transaction [1]
--range_size=N Range size for range SELECT queries [100]
--auto_inc[=on|off] Use AUTO_INCREMENT column as Primary Key (for MySQL), or its alternatives in other DBMS. When disabled, use client-generated IDs [on]
--delete_inserts=N Number of DELETE/INSERT combinations per transaction [1]
--tables=N Number of tables [1]
--mysql_storage_engine=STRING Storage engine, if MySQL is used [innodb]
--non_index_updates=N Number of UPDATE non-index queries per transaction [1]
--table_size=N Number of rows per table [10000]
--pgsql_variant=STRING Use this PostgreSQL variant when running with the PostgreSQL driver. The only currently supported variant is 'redshift'. When enabled, create_secondary is automatically disabled, and delete_inserts is set to 0
--simple_ranges=N Number of simple range SELECT queries per transaction [1]
--order_ranges=N Number of SELECT ORDER BY queries per transaction [1]
--range_selects[=on|off] Enable/disable all range SELECT queries [on]
--point_selects=N Number of point SELECT queries per transaction [10]
Ponownie omówimy tutaj najważniejsze opcje. Przede wszystkim masz kontrolę nad tym, jak dokładnie będzie wyglądać transakcja. Ogólnie rzecz biorąc, składa się z różnych typów zapytań - INSERT, DELETE, różnego typu SELECT (wyszukiwanie punktu, zakres, agregacja) oraz UPDATE (indeksowane, nieindeksowane). Korzystanie ze zmiennych, takich jak:
--distinct_ranges=N Number of SELECT DISTINCT queries per transaction [1]
--sum_ranges=N Number of SELECT SUM() queries per transaction [1]
--index_updates=N Number of UPDATE index queries per transaction [1]
--delete_inserts=N Number of DELETE/INSERT combinations per transaction [1]
--non_index_updates=N Number of UPDATE non-index queries per transaction [1]
--simple_ranges=N Number of simple range SELECT queries per transaction [1]
--order_ranges=N Number of SELECT ORDER BY queries per transaction [1]
--point_selects=N Number of point SELECT queries per transaction [10]
--range_selects[=on|off] Enable/disable all range SELECT queries [on]
Możesz zdefiniować, jak powinna wyglądać transakcja. Jak widać, patrząc na wartości domyślne, większość zapytań to SELECTy - głównie selekcje punktowe, ale także różne typy SELECTów zakresowych (możesz je wyłączyć, ustawiając range_selects na off). Możesz dostosować obciążenie, aby zwiększyć obciążenie związane z zapisem, zwiększając liczbę aktualizacji lub zapytań INSERT/DELETE. Możliwe jest również dostosowanie ustawień związanych z indeksami wtórnymi, automatycznym przyrostem, ale także rozmiarem zestawu danych (liczba tabel i ile wierszy powinna zawierać każda z nich). Pozwala to całkiem nieźle dostosować obciążenie.
--skip_trx[=on|off] Don't start explicit transactions and execute all queries in the AUTOCOMMIT mode [off]
To kolejne ustawienie, bardzo ważne podczas pracy z proxy. Domyślnie SysBench będzie próbował wykonać zapytania w jawnej transakcji. W ten sposób zestaw danych pozostanie spójny i nie będzie naruszony:SysBench na przykład wykona INSERT i DELETE w tym samym wierszu, upewniając się, że zestaw danych nie będzie rósł (wpływając na twoją zdolność do odtworzenia wyników). Jednak serwery proxy będą inaczej traktować transakcje jawne — wszystkie zapytania wykonywane w ramach transakcji powinny być wykonywane na tym samym hoście, co eliminuje możliwość skalowania obciążenia. Należy pamiętać, że wyłączenie transakcji spowoduje, że zestaw danych będzie odbiegał od punktu początkowego. Może to również powodować pewne problemy, takie jak zduplikowane błędy klucza lub tym podobne. Aby móc wyłączyć transakcje, możesz również przyjrzeć się:
--mysql-ignore-errors=[LIST,...] list of errors to ignore, or "all" [1213,1020,1205]
To ustawienie pozwala określić kody błędów z MySQL, które SysBench powinien zignorować (i nie zabijać połączenia). Na przykład, aby zignorować błędy takie jak:błąd 1062 (zduplikowany wpis „6” dla klucza „PRIMARY”), należy przekazać następujący kod błędu:--mysql-ignore-errors=1062
Co również ważne, każdy benchmark powinien prezentować sposób udostępnienia zestawu danych do testów, uruchomienia ich, a następnie oczyszczenia go po zakończeniu testów. Odbywa się to za pomocą poleceń „przygotuj”, „uruchom” i „oczyść”. Pokażemy, jak to się robi w następnej sekcji.
Przykłady
W tej sekcji omówimy kilka przykładów zastosowań SysBench. Jak wspomniano wcześniej, skupimy się na dwóch najpopularniejszych testach porównawczych - OLTP tylko do odczytu i OLTP do odczytu/zapisu. Czasami może mieć sens użycie innych testów porównawczych, ale przynajmniej będziemy w stanie pokazać, jak te dwa można dostosować.
Wyszukiwania klucza głównego
Przede wszystkim musimy zdecydować, który benchmark uruchomimy, tylko do odczytu czy do odczytu i zapisu. Technicznie rzecz biorąc, nie ma to znaczenia, ponieważ możemy usunąć zapisy z testu R/W. Skupmy się na wersji tylko do odczytu.
W pierwszym kroku musimy przygotować zestaw danych. Musimy zdecydować, jak duży powinien być. W przypadku tego konkretnego testu porównawczego, przy użyciu ustawień domyślnych (w ten sposób tworzone są indeksy pomocnicze), 1 milion wierszy da ~240 MB danych. Dziesięć tabel, każdy po 1000 000 wierszy to 2,4 GB:
[email protected]:~# du -sh /var/lib/mysql/sbtest/
2.4G /var/lib/mysql/sbtest/
[email protected]:~# ls -alh /var/lib/mysql/sbtest/
total 2.4G
drwxr-x--- 2 mysql mysql 4.0K Jun 1 12:12 .
drwxr-xr-x 6 mysql mysql 4.0K Jun 1 12:10 ..
-rw-r----- 1 mysql mysql 65 Jun 1 12:08 db.opt
-rw-r----- 1 mysql mysql 8.5K Jun 1 12:12 sbtest10.frm
-rw-r----- 1 mysql mysql 240M Jun 1 12:12 sbtest10.ibd
-rw-r----- 1 mysql mysql 8.5K Jun 1 12:10 sbtest1.frm
-rw-r----- 1 mysql mysql 240M Jun 1 12:10 sbtest1.ibd
-rw-r----- 1 mysql mysql 8.5K Jun 1 12:10 sbtest2.frm
-rw-r----- 1 mysql mysql 240M Jun 1 12:10 sbtest2.ibd
-rw-r----- 1 mysql mysql 8.5K Jun 1 12:10 sbtest3.frm
-rw-r----- 1 mysql mysql 240M Jun 1 12:10 sbtest3.ibd
-rw-r----- 1 mysql mysql 8.5K Jun 1 12:10 sbtest4.frm
-rw-r----- 1 mysql mysql 240M Jun 1 12:10 sbtest4.ibd
-rw-r----- 1 mysql mysql 8.5K Jun 1 12:11 sbtest5.frm
-rw-r----- 1 mysql mysql 240M Jun 1 12:11 sbtest5.ibd
-rw-r----- 1 mysql mysql 8.5K Jun 1 12:11 sbtest6.frm
-rw-r----- 1 mysql mysql 240M Jun 1 12:11 sbtest6.ibd
-rw-r----- 1 mysql mysql 8.5K Jun 1 12:11 sbtest7.frm
-rw-r----- 1 mysql mysql 240M Jun 1 12:11 sbtest7.ibd
-rw-r----- 1 mysql mysql 8.5K Jun 1 12:11 sbtest8.frm
-rw-r----- 1 mysql mysql 240M Jun 1 12:11 sbtest8.ibd
-rw-r----- 1 mysql mysql 8.5K Jun 1 12:12 sbtest9.frm
-rw-r----- 1 mysql mysql 240M Jun 1 12:12 sbtest9.ibd
To powinno dać ci wyobrażenie, ile chcesz stołów i jak duże powinny być. Powiedzmy, że chcemy przetestować obciążenie pamięci, więc chcemy utworzyć tabele, które zmieszczą się w puli buforów InnoDB. Z drugiej strony chcemy również upewnić się, że jest wystarczająco dużo stołów, aby nie stały się wąskim gardłem (lub aby liczba stołów odpowiadała temu, czego można się spodziewać w konfiguracji produkcyjnej). Przygotujmy nasz zbiór danych. Należy pamiętać, że domyślnie SysBench szuka schematu „sbtest”, który musi istnieć przed przygotowaniem zestawu danych. Może być konieczne utworzenie go ręcznie.
[email protected]:~# sysbench /root/sysbench/src/lua/oltp_read_only.lua --threads=4 --mysql-host=10.0.0.126 --mysql-user=sbtest --mysql-password=pass --mysql-port=3306 --tables=10 --table-size=1000000 prepare
sysbench 1.1.0-2e6b7d5 (using bundled LuaJIT 2.1.0-beta3)
Initializing worker threads...
Creating table 'sbtest2'...
Creating table 'sbtest3'...
Creating table 'sbtest4'...
Creating table 'sbtest1'...
Inserting 1000000 records into 'sbtest2'
Inserting 1000000 records into 'sbtest4'
Inserting 1000000 records into 'sbtest3'
Inserting 1000000 records into 'sbtest1'
Creating a secondary index on 'sbtest2'...
Creating a secondary index on 'sbtest3'...
Creating a secondary index on 'sbtest1'...
Creating a secondary index on 'sbtest4'...
Creating table 'sbtest6'...
Inserting 1000000 records into 'sbtest6'
Creating table 'sbtest7'...
Inserting 1000000 records into 'sbtest7'
Creating table 'sbtest5'...
Inserting 1000000 records into 'sbtest5'
Creating table 'sbtest8'...
Inserting 1000000 records into 'sbtest8'
Creating a secondary index on 'sbtest6'...
Creating a secondary index on 'sbtest7'...
Creating a secondary index on 'sbtest5'...
Creating a secondary index on 'sbtest8'...
Creating table 'sbtest10'...
Inserting 1000000 records into 'sbtest10'
Creating table 'sbtest9'...
Inserting 1000000 records into 'sbtest9'
Creating a secondary index on 'sbtest10'...
Creating a secondary index on 'sbtest9'...
Gdy mamy już nasze dane, przygotujmy polecenie uruchomienia testu. Chcemy przetestować wyszukiwanie klucza podstawowego, dlatego wyłączymy wszystkie inne typy SELECT. Wyłączymy również przygotowane instrukcje, ponieważ chcemy testować zwykłe zapytania. Przetestujemy niską współbieżność, powiedzmy 16 wątków. Nasze polecenie może wyglądać jak poniżej:
sysbench /root/sysbench/src/lua/oltp_read_only.lua --threads=16 --events=0 --time=300 --mysql-host=10.0.0.126 --mysql-user=sbtest --mysql-password=pass --mysql-port=3306 --tables=10 --table-size=1000000 --range_selects=off --db-ps-mode=disable --report-interval=1 run
Co my tu zrobiliśmy? Ustawiliśmy liczbę wątków na 16. Zdecydowaliśmy, że chcemy, aby nasz benchmark działał przez 300 sekund, bez limitu wykonywanych zapytań. Zdefiniowaliśmy łączność z bazą danych, liczbę tabel i ich rozmiar. Wyłączyliśmy również wszystkie SELECTy z zakresu, zablokowaliśmy również przygotowane instrukcje. Na koniec ustawiamy interwał raportów na jedną sekundę. Tak może wyglądać przykładowe wyjście:
[ 297s ] thds: 16 tps: 97.21 qps: 1127.43 (r/w/o: 935.01/0.00/192.41) lat (ms,95%): 253.35 err/s: 0.00 reconn/s: 0.00
[ 298s ] thds: 16 tps: 195.32 qps: 2378.77 (r/w/o: 1985.13/0.00/393.64) lat (ms,95%): 189.93 err/s: 0.00 reconn/s: 0.00
[ 299s ] thds: 16 tps: 178.02 qps: 2115.22 (r/w/o: 1762.18/0.00/353.04) lat (ms,95%): 155.80 err/s: 0.00 reconn/s: 0.00
[ 300s ] thds: 16 tps: 217.82 qps: 2640.92 (r/w/o: 2202.27/0.00/438.65) lat (ms,95%): 125.52 err/s: 0.00 reconn/s: 0.00
Co sekundę widzimy migawkę statystyk obciążenia. Jest to bardzo przydatne do śledzenia i wykreślania — raport końcowy zawiera tylko średnie. Wyniki pośrednie umożliwią śledzenie wyników z sekundy na sekundę. Raport końcowy może wyglądać jak poniżej:
SQL statistics:
queries performed:
read: 614660
write: 0
other: 122932
total: 737592
transactions: 61466 (204.84 per sec.)
queries: 737592 (2458.08 per sec.)
ignored errors: 0 (0.00 per sec.)
reconnects: 0 (0.00 per sec.)
Throughput:
events/s (eps): 204.8403
time elapsed: 300.0679s
total number of events: 61466
Latency (ms):
min: 24.91
avg: 78.10
max: 331.91
95th percentile: 137.35
sum: 4800234.60
Threads fairness:
events (avg/stddev): 3841.6250/20.87
execution time (avg/stddev): 300.0147/0.02
Znajdziesz tutaj informacje o wykonanych zapytaniach i innych instrukcjach (BEGIN/COMMIT). Dowiesz się, ile transakcji zostało wykonanych, ile było błędów, jaka była przepustowość i łączny czas. Możesz także sprawdzić metryki opóźnień i rozkład zapytań w wątkach.
Gdybyśmy byli zainteresowani dystrybucją opóźnień, moglibyśmy również przekazać argument „--histogram” do SysBench. Daje to dodatkowe dane wyjściowe, takie jak poniżej:
Latency histogram (values are in milliseconds)
value ------------- distribution ------------- count
29.194 |****** 1
30.815 |****** 1
31.945 |*********** 2
33.718 |****** 1
34.954 |*********** 2
35.589 |****** 1
37.565 |*********************** 4
38.247 |****** 1
38.942 |****** 1
39.650 |*********** 2
40.370 |*********** 2
41.104 |***************** 3
41.851 |***************************** 5
42.611 |***************** 3
43.385 |***************** 3
44.173 |*********** 2
44.976 |**************************************** 7
45.793 |*********************** 4
46.625 |*********** 2
47.472 |***************************** 5
48.335 |**************************************** 7
49.213 |*********** 2
50.107 |********************************** 6
51.018 |*********************** 4
51.945 |**************************************** 7
52.889 |***************** 3
53.850 |***************** 3
54.828 |*********************** 4
55.824 |*********** 2
57.871 |*********** 2
58.923 |*********** 2
59.993 |****** 1
61.083 |****** 1
63.323 |*********** 2
66.838 |****** 1
71.830 |****** 1
Gdy osiągniemy dobre wyniki, możemy wyczyścić dane:
sysbench /root/sysbench/src/lua/oltp_read_only.lua --threads=16 --events=0 --time=300 --mysql-host=10.0.0.126 --mysql-user=sbtest --mysql-password=pass --mysql-port=3306 --tables=10 --table-size=1000000 --range_selects=off --db-ps-mode=disable --report-interval=1 cleanup
Natężony ruch związany z zapisem
Wyobraźmy sobie, że chcemy wykonać duże obciążenie związane z zapisem (ale nie tylko do zapisu) i na przykład przetestować wydajność podsystemu I/O. Przede wszystkim musimy zdecydować, jak duży powinien być zbiór danych. Przyjmiemy ~48 GB danych (20 tabel po 10 000 000 wierszy). Musimy to przygotować. Tym razem użyjemy testu porównawczego odczytu i zapisu.
[email protected]:~# sysbench /root/sysbench/src/lua/oltp_read_write.lua --threads=4 --mysql-host=10.0.0.126 --mysql-user=sbtest --mysql-password=pass --mysql-port=3306 --tables=20 --table-size=10000000 prepare
Po wykonaniu tej czynności możemy dostosować ustawienia domyślne, aby wymusić więcej zapisów w kombinacji zapytań:
[email protected]:~# sysbench /root/sysbench/src/lua/oltp_read_write.lua --threads=16 --events=0 --time=300 --mysql-host=10.0.0.126 --mysql-user=sbtest --mysql-password=pass --mysql-port=3306 --tables=20 --delete_inserts=10 --index_updates=10 --non_index_updates=10 --table-size=10000000 --db-ps-mode=disable --report-interval=1 run
Jak widać na podstawie wyników pośrednich, transakcje są teraz po stronie wymagającej dużej liczby zapisów:
[ 5s ] thds: 16 tps: 16.99 qps: 946.31 (r/w/o: 231.83/680.50/33.98) lat (ms,95%): 1258.08 err/s: 0.00 reconn/s: 0.00
[ 6s ] thds: 16 tps: 17.01 qps: 955.81 (r/w/o: 223.19/698.59/34.03) lat (ms,95%): 1032.01 err/s: 0.00 reconn/s: 0.00
[ 7s ] thds: 16 tps: 12.00 qps: 698.91 (r/w/o: 191.97/482.93/24.00) lat (ms,95%): 1235.62 err/s: 0.00 reconn/s: 0.00
[ 8s ] thds: 16 tps: 14.01 qps: 683.43 (r/w/o: 195.12/460.29/28.02) lat (ms,95%): 1533.66 err/s: 0.00 reconn/s: 0.00
Zrozumienie wyników
Jak pokazaliśmy powyżej, SysBench to świetne narzędzie, które może pomóc w określeniu niektórych problemów z wydajnością MySQL lub MariaDB. Można go również użyć do wstępnego dostrojenia konfiguracji bazy danych. Oczywiście musisz pamiętać, że aby jak najlepiej wykorzystać swoje testy porównawcze, musisz zrozumieć, dlaczego wyniki wyglądają tak, jak wyglądają. Wymagałoby to wglądu w wewnętrzne metryki MySQL za pomocą narzędzi monitorujących, na przykład ClusterControl. Jest to dość ważne, aby pamiętać – jeśli nie rozumiesz, dlaczego wydajność była taka, jak była, możesz wyciągnąć nieprawidłowe wnioski z testów porównawczych. Zawsze istnieje wąskie gardło, a SysBench może pomóc w rozwiązaniu problemów z wydajnością, które należy następnie zidentyfikować.