目次
とある日
仕事で、MySQLのデータベースに対してベンチマークをしたいなと思いました。
そこで前々から気になってた「mysqlslap」を試してみました。
今回は、「mysqlslap」を使ってみようという内容です。
mysqlslapとは
mysqlslap は MySQL サーバーのクライアント負荷をエミュレートし、各段階のタイミングをレポートする診断プログラムです。
MySQL :: MySQL 8.0 リファレンスマニュアル :: 4.5.8 mysqlslap — ロードエミュレーションクライアント
はじめは、任意のデータベースのテーブルに対してSQLを好きに実行して負荷をかけられるものだと認識していましたが違うみたいです。
mysqlslap専用のデータベースに仮のテーブルを作成してオプションにあったSQLを実行して負荷を計るようです。
mysqlslap は以下の 3 段階で実行されます。
- テストに使用するスキーマ、テーブル、およびオプションでストアドプログラムまたはデータを作成します。
- 負荷テストを実行します。
- クリーンアップ (接続の解除、指定した場合はテーブルの削除) を実行します。
使ってみた
テーブルを作成してSQLを実行することもできるみたいですが、今回はシンプルな使い方をしてみます。
実行環境
docker composeを使って、負荷をかけるコンテナと負荷をかけられるコンテナの2つを用意します。
- 負荷をかけるコンテナ
- 負荷をかけられるコンテナ
version: "3" services: slap: image: diceone/mysqlslap container_name: mysqlslap db: image: mysql:8.0.33 container_name: mysqlloadtest environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: test MYSQL_USER: docker MYSQL_PASSWORD: docker TZ: "Asia/Tokyo" command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci volumes: - ../../MySQL/settings/my.cnf:/etc/mysql/conf.d/my.cnf - ../../MySQL/settings/mylogin.sh:/root/mylogin.sh
手順
- MySQL 8.0.33コンテナ起動
- mysqlslapコマンドを実行
MySQL 8.0.33コンテナ起動
MySQLLoadTest> docker-compose up -d [+] Running 2/2 - Container mysqlloadtest Running 0.0s - Container mysqlslap Started 0.4s MySQLLoadTest> docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3cc2fe3af3ec mysql:8.0.33 "docker-entrypoint.s…" 3 hours ago Up 3 hours 3306/tcp, 33060/tcp mysqlloadtest
この際、IPアドレスをメモっておく。
(dockerのネットワーク見なくてもhostsファイル見ればいいの初めて知りました)
MySQLLoadTest> docker-compose exec db bash bash-4.4# cat /etc/hosts 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters 192.168.16.3 3cc2fe3af3ec
このコンテナなのデータベース(192.168.16.3)に対して接続を行います。
mysqlslapコマンドを実行
mysqlslapのコンテナは常時起動しないので起動コマンドと一緒にmysqlslapコマンドを実行します。
(PowerShellで実行しているのでバッククォートで区切ってます)
docker compose run slap ` mysqlslap --no-defaults --auto-generate-sql ` --engine=innodb --auto-generate-sql-add-autoincrement ` --host=192.168.16.3 --port=3306 -u root -proot ` --number-int-cols=10 --number-char-cols=10 --iterations=10 --concurrency=50 ` --auto-generate-sql-write-number=10 --number-of-queries=10 --auto-generate-sql-load-type=read
待ってると結果が表示される。
MySQLLoadTest>docker compose run slap ` >> mysqlslap --no-defaults --auto-generate-sql ` >> --engine=innodb --auto-generate-sql-add-autoincrement ` >> --host=192.168.16.3 --port=3306 -u root -proot ` >> --number-int-cols=10 --number-char-cols=10 --iterations=10 --concurrency=50 ` >> --auto-generate-sql-write-number=10 --number-of-queries=10 --auto-generate-sql-load-type=read Benchmark Running for engine innodb Average number of seconds to run all queries: 0.018 seconds Minimum number of seconds to run all queries: 0.016 seconds Maximum number of seconds to run all queries: 0.027 seconds Number of clients running queries: 50 Average number of queries per client: 0
コマンドオプション
先程使用したオプション一覧
オプション名 | 説明 |
---|---|
--no-defaults | オプションファイルを読み取らない |
--auto-generate-sql | SQL ステートメントがファイルおよびコマンドオプションを使用して指定されない場合、自動的に生成 |
--engine | テーブルの作成に使用するストレージエンジン |
--auto-generate-sql-add-autoincrement | AUTO_INCREMENT カラムを自動生成されたテーブルに追加 |
--host | MySQL サーバーがあるホスト |
--port | 接続用の TCP/IP ポート番号 |
--user | サーバーへの接続時に使用する MySQL ユーザー名 |
--password | サーバーに接続する際に使用するパスワード |
--number-int-cols | --auto-generate-sql が指定された場合に使用する INT カラムの数 |
--number-char-cols | --auto-generate-sql が指定された場合に使用する VARCHAR カラムの数 |
--iterations | 実行するテストの回数 |
--concurrency | SELECT ステートメントを発行する際、シミュレートするクライアントの数 |
--auto-generate-sql-write-number | 各スレッドで実行する行挿入の回数 |
--number-of-queries | 各クライアントのクエリー数をおよそこの数に制限 |
--auto-generate-sql-load-type | テストの負荷タイプを指定します |
オプションの区分け
- 負荷先の設定
--host
--port
--user
--password
- 負荷をかける環境の設定
--engine
- 負荷設定
--iterations
--concurrency
--auto-generate-sql-load-type
--no-defaults
--auto-generate-sql
- 負荷SQLの設定
--auto-generate-sql-add-autoincrement
--number-int-cols
--number-char-cols
--auto-generate-sql-write-number
--number-of-queries
重要なオプションの解説
--auto-generate-sql-load-type
テストの負荷タイプを指定します。 許可される値は、
read
(テーブルのスキャン)、write
(テーブルに挿入)、key
(主キーの読み取り)、update
(主キーの更新)、またはmixed
(挿入とスキャンして選択が半分ずつ) です。 デフォルトはmixed
です。
実行されるSQLが異なります。
general_logを取得して確認します。
readの場合
SELECT intcol1,charcol1 FROM t1
writeの場合
INSERT INTO t1 VALUES (NULL,1674308135,'TKiz9ItDX763hOQSRIxHlEKHK5dY8NzTbhSkrLpELw9uCbMftKoXQ8gnDHBDZAi8rBlaOagdWpYbGm616vYPvC41MFEvPx380oaGFEmd3ICB4JC36dS1pY23f9ywyu')
keyの場合
SELECT id from t1
updateとmixedは結果変わらなかったので割愛します。
おそらく実行数が少ないとできないのかなと推測しています。
--concurrency
同時実行数を制御できます。
mysqlslap実行中にprocesslist見れば実行数が確認できます。
ただ、一回のクエリの時間が短いのでこの値を増やすことで確認できます。
(root@localhost) [mysql] 8.0.33 > show full processlist\G; *************************** 1. row *************************** Id: 5 User: event_scheduler Host: localhost db: NULL Command: Daemon Time: 13448 State: Waiting on empty queue Info: NULL *************************** 2. row *************************** Id: 2976 User: root Host: localhost db: mysql Command: Query Time: 0 State: init Info: show full processlist *************************** 3. row *************************** Id: 6094 User: root Host: 192.168.16.2:39572 db: mysqlslap Command: Query Time: 0 State: waiting for handler commit Info: INSERT INTO t1 VALUES (NULL,611402892,64686043,530048534,839439115,1615664209,791065520,1798982550,553597150,776664701,895488819,'S5pGAuJYH512qcYWEeb9FnsTjap5kMc4SPLWCY2LdvNKYoieQHoh5Y2g6sdiEDnaW0xiYr41nJDJ7vxaDd7A2Aq8uJj0YWR2MOduFhn2s1D0w3Q1YPBabtbLCIMkgh','f25GoCxb7hcKhPFzQoPeEsXpEczSKf9zZ67LIwpPePeJqtBHZcngKATQmLuzsvqQ1yfCuSdOm7cS1ndQFO6bRS25powhknzddXhNrJodIOyJBbeQsktJCvGtcDRCsQ','hTpNkhaYAso84rki9cQ3nXq3GQ8jW0ACTrbEY1ejtRrxIRXS3qXiDDeTYmD2nFEG6hMfi1ESK5HeZpySXLBkbpD7RQ9EZGNgplBOePsyW1TvqRODpRxG83NbTOivY5','bMimmLBWJZXoTE8lRx4PD4SSXpsDkPABftxPE0nPaI6vYEY03cH8Ydc3IK9vdJ6G4wZAwKSMfaH3ghvjHCrhhJlsfmfHxlP2Zz4MBYci6umeRhLlm4IJNvBvhqCXST','PtSTFg2kE0e0fxisiKptf4ojzWZ3ttZIntnuPhega8g56EpgQeZ6jEhak6Wd03nfwaPMG4ui4Qn2hcjzF85qMeGylmRlpEGehhspdmXiCIkluJl1KiriL0ZymsjS7r','6gYqTAS0sYISA4gv60Txaip7gcsF4r62XXk0hC0PkAlmEPhKP3AsdzzIbjPXaOP5v95SLxly7WkMoIa5Dkxqcp03YQb7isCT2AxF7aD74qLk0vqDYn38cwB9Me8wXC','PPMMgMwmTsSqTSdJh96cHbYLcmrkaEwzfBDCZ1qumIkFmDaJNYvY7KlbydBZj0YFBeRcfHWPb6gDJEYafJ7eXsEWLPv5PJKSxf4dwQ2NObcch0AKJ9zj25DNM0KgJg','8HB5u7XoMoNqO5qQH2c8lWDqlSq689eGIqL4pltCP82h5t7NnjXY5dMr5CxDDbLYHjS7KDBlMDQJyPil16H6jXxgbutpMEDXpZe1npm9v4StW3XX1oTcCRGnD1Sb7Z','7p7dquJTvEZFzvIWIBBonN73AK4Xo44ntBGjxbCspe8hPIBkWMOHdNDoj9BNDFAyJRiGum9cO9HiJSIhjarKx40g5BwBRy9ePjuCWvomw5SGPex0CgL9kLiiPetkcu','MueG684mm0j788ly9yeM7Fbhp0Jikoc6a6Fg6BIt31sC9d2ARYYRn88c0KAl0fjalq6k1OTxPL9Qq3TAbtdNtdrupuXhZ6FApDmqdFnuSoDJraLRRqiLRP79Jeqkcy') 3 rows in set (0.00 sec)
〆
はじめにイメージしていた使い方ではなかったですが、すごく手軽に試せることがわかりました。
Amazon AuroraにR7gが来たので試してみたいなと思います。
参考記事
実際のワークロードに近いSQLの負荷テストをmysqlslapのような感覚で行う方法を考える - GMOインターネットグループ グループ研究開発本部(次世代システム研究室)
MySQL を使って EC2 r6g.large vs r5.large(mysqlslap 対決)をやってみた - Qiita
MySQL :: MySQL 8.0 リファレンスマニュアル :: 4.5.8 mysqlslap — ロードエミュレーションクライアント