MySQLのベンチマーク測定:mysqlslapについての紹介

サムネイル

はじめに

みなさんこんにちは、LC開発部の神畠です。
普段は、24時間365日で稼働する大規模サービス基盤の課題解決に取り組み、さらなる高品質化と安定運用の実現を目指しています。
今回は業務の中でmysqlslapを利用する機会があったため紹介をしたいと思います。

mysqlslapはMySQLサーバーのクライアント負荷を測定する場合に使われるサービスになります。
本稿ではmysqlslapの概要や実行方法、設定値などについての説明をするとともに、実際に実行するにあたって留意すべき点も合わせて共有します。

mysqlslapの概要

前述の通りMySQLサーバーのクライアント負荷をエミュレートするサービスになります。 後述しますが試験もコマンド一つで実行し、ベンチマークとしてクエリ実行時間などを容易に測定が可能です。
また、MySQLクライアントをすでに導入している場合は標準でインストールされています。(別のサーバ等でロケーションを変えて実行する場合は別途インストールが必要になります。)

shell> mysqlslap [options]

対応バージョンや測定方法およびオプションは下記のようになります。

項目
設定できる主なオプション例 --no-defaults:オプションファイル(my.cnfなど)を読み取らない。例外的に.mylogin.cnfファイルは作成している場合は読み取られる。
--user:サーバーへの接続時に使用するMySQLユーザー名
--password:サーバーに接続する際に使用するパスワード
--host:MySQLサーバーがあるホスト
--port:接続用のTCP/IPポート番号
--engine:使用するDBエンジン
--auto-generate-sql:テストデータ自動生成
--auto-generate-sql-load-type:テストタイプはSELECT
--auto-generate-sql-add-autoincrement:AUTO_INCREMENTカラムを自動生成されたテーブルに追加
--number-int-cols:--auto-generate-sqlが指定された場合に使用するINTカラムの数
--number-char-cols:--auto-generate-sqlが指定された場合に使用するVARCHARカラムの数
--auto-generate-sql-write-number:各スレッドで実行する行挿入の回数
--auto-generate-sql-execute-number:自動的に生成するクエリーの数を指定
--concurrency:SELECT ステートメントを発行
対応バージョン MySQL 5.1.4から最新のMySQL 8.4までサポートされています。(2025年6月現在)
測定方法例 1. テストに使用するスキーマ、テーブル、およびオプションでストアドプログラムまたはデータを作成。
2. mysqlslapコマンドを実行し実行時間からパフォーマンスを測定
3. mysqlslapコマンドにクエリを指定して実行し実行時間からパフォーマンスを測定
4. クリーンアップ (接続の解除、指定した場合はテーブルの削除) を実行。
・クエリのステートメントはSELECT、INSERT、UPDATE、MIXED(各種ステートメント混合)をそれぞれ均等に選定 
 ・新規クエリ実行時はキャッシュを考慮して直前にMySQL再起動とLinux再起動を実施

ベンチマークテスト実行例

実行したいサーバから下記のようにmysqlslapコマンドを実行することで負荷試験の実施ができます。
実行時に下記のようにテーブル行数やクエリ数、繰り返し回数などを指定して実行できます。

実行例1

auto-generate-sqlを指定すると、自動的に検証用のスキーマを作成して検証用SQLを発行し負荷検証を行います。 このパターンは事前にクエリを用意せずに検証が可能です。
auto-generate-sql-load-typeでステートメントを指定できます。ステートメントの設定は下記表の通りになります。

各種ステートメントの実行には指定したユーザーに実行権限が必要なのでその点はご注意ください。

auto-generate-sql-load-typeの値 設定
read テーブルスキャンをするSELECT文を実行
key 主キーを使ったSELECT文を実行
update UPDATE文の実行
write INSERT文の実行
mixed テーブルスキャンをするSELECT文とINSERT文を半分ずつ実行

下記コマンドでは負荷検証でテスト用レコードを10000行作成したうえで、100個のクライアントがSELECT文の実行クエリを同時に10回実行する動作を5回繰り返す負荷検証を実施しています。

mysqlslap \
  --no-defaults \
  --user=root \
  --password \
  --host=127.0.0.1 \
  --port=3306 \
  --create-schema=chatlink \
  --engine=InnoDB \
  --auto-generate-sql \
  --auto-generate-sql-load-type=read \
  --auto-generate-sql-add-autoincrement \
  --number-int-cols=3 \
  --number-char-cols=2 \
  --auto-generate-sql-write-number=10000 \
  --auto-generate-sql-execute-number=10 \
  --concurrency=100 \
  --iterations=5
 
実行結果:
Benchmark
        Running for engine InnoDB
        Average number of seconds to run all queries: 2.275 seconds
        Minimum number of seconds to run all queries: 2.250 seconds
        Maximum number of seconds to run all queries: 2.328 seconds
        Number of clients running queries: 100
        Average number of queries per client: 10

実行例2

createやqueryでテーブルを作成して実際にクエリを指定して負荷検証を行うことができます。
用途としては主にスロークエリなど、特定のクエリのパフォーマンスを見たい場合に使われるものになります。

mysqlslap \
   --no-defaults \
   --user=root \
   --password \
   --host=127.0.0.1 \
   --port=3306 \
   --delimiter=";" \
   --create="CREATE TABLE test_table (id int);INSERT INTO test_table VALUES (23)" \
   --query="SELECT * FROM test_table" \
   --concurrency=100 \
   --iterations=10 \
 
実行結果:
Benchmark
        Average number of seconds to run all queries: 0.165 seconds
        Minimum number of seconds to run all queries: 0.062 seconds
        Maximum number of seconds to run all queries: 1.062 seconds
        Number of clients running queries: 100
        Average number of queries per client: 1

実行にあたっての留意点

MySQLクエリは一度実行した後InnoDB Buffer Poolの仕様でキャッシュが効くことから、2回目以降の実行はクエリが即時に実行されます。 また、その流れでOSキャッシュが効いているかどうかも事前調査しました。調査の結果、MySQLクエリ実行時に、設定によってはOSキャッシュが効いていたことがわかりました。 MySQLクエリが発行されると下記の流れでキャッシュの処理を実施しています。

  1. InnoDB Buffer Poolにデータがあるかを確認
  2. InnoDB Buffer Poolにデータがなければ、OSのファイルキャッシュにデータがあるか確認
  3. OSのファイルキャッシュにデータがあれば、ディスクI/Oを発生させずにOSキャッシュからデータを取得する
  4. OSのファイルキャッシュにデータがなければディスクからデータを読み込む

またInnoDBにはinnodb_flush_methodというパラメータがあり、未指定の場合だとOSキャッシュを参照しますが、値をO_DIRECTを設定するとOSのファイルキャッシュをバイパスできます。

今回は確認の際にキャッシュを考慮せず、純粋なクエリの実行時間でパフォーマンスを測定したかったため、mysqlslap実行前にMySQLとOS再起動を両方実施して測定しました。
純粋なクエリのパフォーマンス測定という観点で見ると、連続してmysqlslapコマンドを実行して測定する場合は、実行前にMySQL再起動を実施するなど測定の精度が担保できるかの考慮は必要になります。
このようにmysqlslapを利用したベンチマークテストを行う際は、要件によって測定方法が異なることを意識していただければと思います。

おわりに

今回はmysqlslapについての概要と実際の実行例も合わせて紹介をさせていただきました。
前述の通りmysqlslapはコマンドを実行するだけでMySQLの負荷検証を行い、パフォーマンスを測定できるので非常に便利なツールだと思います。
他のサービスの負荷を確認したいという要件であればその限りではありませんが、純粋にMySQLの負荷検証を実施したいという要件であれば有用な選択肢となると考えています。