TiDBでベンチーマーク 〜 sysbench

## はじめに

tidbの性能評価として、ベンチマークツールを使うことがよくあります。
本記事ではsysbenchからTiDBへの接続について書きます。

なお記事書いておいてなんですが筆者は「DBのベンチマークは実際のワークロードに近い形で！」主義者です 😀

## 注意

TiDB CloudのパブリックエンドポイントはTLS必須ですが、ベンチマークツールでTLS対応はそこまで多くありません。また、TLSのオーバーヘッドもあります。実際に本番で利用する接続形態（PrivateLink等）で接続して実施するのが良いでしょう。

またTiDB Cloud Serverlessは従量課金なため、相当の負荷をかけ続けるベンチマークだと都度費用が発生することにもなります（また、課金上限を設定している場合はスロットリングの可能性もあります）ご注意ください。

## sysbench

https://github.com/akopytov/sysbench

sysbenchはDB(MySQL/Postgres) や、file IO, cpuといった様々なベンチマークを実施するツールです。Luaスクリプトでベンチマークを記述することができる柔軟性が大きな特徴です。

MacOSの場合のインストールは、Homebrewを使って `brew install sysbench` でできます。MySQLドライバを利用するため、適当な方法でmysqlクライアントをインストールしておきます。

### sysbenchのオプション

sysbenchには、オプションとして テスト種類とコマンド(prepare, run) を与える必要があります。
データベースのテストも標準で付属しており、下記があります。

- oltp_read_only
- oltp_write_only
- oltp_read_write
- oltp_insert
- oltp_delete
- oltp_update_index
- oltp_update_non_index
- oltp_point_select
- select_random_point
- select_random_ranges
- bulk_insert

それぞれ、`help` コマンドでヘルプが出ます。

```bash
sysbench oltp_read_write help

sysbench 1.0.20 (using system LuaJIT 2.1.1720049189)

oltp_read_write options:
  --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]
  --create_secondary[=on|off]   Create a secondary index in addition to the PRIMARY KEY [on]
  --delete_inserts=N            Number of DELETE/INSERT combinations per transaction [1]
  --distinct_ranges=N           Number of SELECT DISTINCT queries per transaction [1]
  --index_updates=N             Number of UPDATE index queries per transaction [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]
  --order_ranges=N              Number of SELECT ORDER BY queries per transaction [1]
  --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
  --point_selects=N             Number of point SELECT queries per transaction [10]
  --range_selects[=on|off]      Enable/disable all range SELECT queries [on]
  --range_size=N                Range size for range SELECT queries [100]
  --secondary[=on|off]          Use a secondary index in place of the PRIMARY KEY [off]
  --simple_ranges=N             Number of simple range SELECT queries per transaction [1]
  --skip_trx[=on|off]           Don't start explicit transactions and execute all queries in the AUTOCOMMIT mode [off]
  --sum_ranges=N                Number of SELECT SUM() queries per transaction [1]
  --table_size=N                Number of rows per table [10000]
  --tables=N                    Number of tables [1]
  ```

基本的には、`sysbench [options] [テスト名] prepare` で必要なデータの準備を行い、`sysbench [options] [テスト名] run` で実行します。終わったら、`sysbench [options] [テスト名] cleanup` でデータを削除します。

optionsには、接続情報などを記載します。基本的に `--option=hogehoge` の形式です。

## TiDB (Playground) での実施

ここでは簡単にPlaygroundを使ってローカルに起動したTiDBに対してsysbenchを実行してみます。

### TiDBの起動

TiUPを利用して起動します。v8.1.1 を利用しました。

```bash
tiup playground v8.1.1
<出力略>
```

### sysbenchの準備

テスト実施のため、データを準備します。sysbenchのは下記のようになります。

```bash

> sysbench --mysql-host=127.0.0.1 --mysql-user=root --mysql-port=4000 --mysql-db=test oltp_read_write prepare
sysbench 1.0.20 (using system LuaJIT 2.1.1720049189)

Creating table 'sbtest1'...
Inserting 10000 records into 'sbtest1'
Creating a secondary index on 'sbtest1'...

```

利用しているオプションは下記です。

- --mysql-host ホスト名
- --mysql-user ユーザー名
- --mysql-db データベース。デフォルトはsbtestというデータベースを使いますが、ここでは標準で作成されているtestを利用
- --mysql-port ポート番号

### sysbenchの実行

準備ができたら、テストを実行します。

```bash
> sysbench --time=10 --threads=4 --mysql-host=127.0.0.1 --mysql-user=root --mysql-port=4000 --mysql-db=test oltp_read_write run
sysbench 1.0.20 (using system LuaJIT 2.1.1720049189)

Running the test with following options:
Number of threads: 4
Initializing random number generator from current time


Initializing worker threads...

Threads started!

SQL statistics:
    queries performed:
        read:                            81018
        write:                           23138
        other:                           11570
        total:                           115726
    transactions:                        5783   (577.84 per sec.)
    queries:                             115726 (11563.36 per sec.)
    ignored errors:                      4      (0.40 per sec.)
    reconnects:                          0      (0.00 per sec.)

General statistics:
    total time:                          10.0077s
    total number of events:              5783

Latency (ms):
         min:                                    4.45
         avg:                                    6.92
         max:                                   22.57
         95th percentile:                        0.00
         sum:                                40011.61

Threads fairness:
    events (avg/stddev):           1445.7500/2.49
    execution time (avg/stddev):   10.0029/0.00

```

利用しているオプションは、下記です。

- --time 実行時間を秒数で指定
- --threads 実行スレッド数を指定

実行後、実行したDMLの種類と件数や、レイテンシの統計情報を表示します。
結果をコントロールするオプションも多数あるので、`sysbench --help` で確認してみてください。

### TLS接続の利用

:::note warn
以下の手順ではHEADのsysbenchを利用しています
:::

sysbenchはmysql clientを利用しているので、最新のmysql clientであればパブリックなCAを使うTiDB Cloud Serverlessには特にオプションの指定もなく接続できます。

ただTiDB Cloud Dedicatedのような独自CAを利用する場合には、オプションを設定する必要があります。

sysbenchのTLS接続オプションは、brewで入るstableのsysbench (v1.0.20) では利用できません。

そのため、まずHEADのsysbenchをインストールする必要があります。

```bash
brew unlink sysbench
brew install sysbench --HEAD
```

その後、TLS接続を利用したテストが実行できるようになります。

```bash
sysbench --mysql-host=[TiDBホスト] --mysql-user=root --mysql-port=4000 --mysql-db=test --mysql-ssl=on --mysql-ssl-ca=[CAファイルパス] --mysql-password=[TiDBパスワード] oltp_read_write prepare
```

利用したオプション

- --mysql-ssl onにするとSSL接続を利用する
- --mysql-ssl-ca CAファイルを指定する

## おわりに

ベンチマークツールは色々なものがありますが、本記事ではお手軽かつ柔軟なsysbenchの利用法について説明しました。実際にやってみると、**ベンチマークの結果と実際のワークロードの負荷には大きな乖離があることも珍しくないです**。ベンチマークが実際のワークロードに近いかをよく考える必要があると思います。