MySQL 8.0.22 で innodb_log_writer_threads の効果を見てみる

これは **[MySQL Advent Calendar 2020](https://qiita.com/advent-calendar/2020/mysql)** 23 日目のエントリです。
昨日は atsuizo さんの**「[MySQLのデータ投入順序とデータファイルサイズのお話](https://atsuizo.hatenadiary.jp/entry/2020/12/22/190923)」**でした。

そして、↓の記事の続きでもあります。

 - **[MySQL を使って EC2 r6g.large vs r5.large（mysqlslap 対決）をやってみた](https://qiita.com/hmatsu47/items/e20c4d69b0af465b0b12)**

前回は MySQL Community Server をインストールした AWS の EC2 インスタンスを使い、Graviton2 プロセッサと Intel プロセッサで `mysqlslap` 対決をしてみましたが、その延長で、`innodb_log_writer_threads`の効果を確かめてみました。

# `innodb_log_writer_threads`とは

MySQL 8.0.22 で追加された InnoDB の設定項目（パラメータ）です。

 - **[innodb_log_writer_threads](https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_log_writer_threads)（MySQL 8.0 Reference Manual）**

MySQL 8.0.11 で導入された Dedicated log writer threads が、低並列な環境ではかえって性能低下をもたらすことがわかったので、無効化できるように追加されました。

※MySQL 5.7 比でも遅くなります。

 - **[
Changes in MySQL 8.0.22 (2020-10-19, General Availability)](https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-22.html)（MySQL 8.0 Release Notes）**より引用

> - ***InnoDB***: Dedicated log writer threads, introduced in MySQL 8.0.11, caused a CPU-bound performance regression on low-concurrency systems. To address this issue, the new innodb_log_writer_threads variable permits disabling dedicated log writer threads so that redo log records are written from the log buffer to the system buffers and flushed from the system buffers to the redo log files by each user thread, which is the behavior prior to the introduction of dedicated log writer threads. Other redo logging optimizations were implemented, including the removal of an unnecessary log closer thread that wasted CPU time, and optimizations to remedy too-aggressive checkpoint activity and excessive flush calls. The issues addressed by this fix also manifested in a LOAD DATA performance regression. (Bug #30088404, Bug #30003849)

# 今回の実験内容

 - 2vCPU / 8vCPU / 32vCPU の各 EC2 インスタンスを使い
   - Graviton2 と Intel（x86_64）の両方で
   - OS は 前回同様 CentOS 8.3
 - innodb_log_writer_threads を ON（デフォルト）/ OFF しながら
 - `--concurrency`（スレッド数）を 150 / 300 / (450) / (600) と変化させながら`mysqlslap`を流す
   - 種別は`mixed`のみ
 - 実行前に`set global max_connections=【スレッド数 +1】;`で最大コネクション数を設定

```
mysqlslap --auto-generate-sql --auto-generate-sql-guid-primary --engine=innodb --number-int-cols=20 --number-char-cols=20 --concurrency=【スレッド数】 --auto-generate-sql-write-number=2000 --auto-generate-sql-execute-number=2000 --auto-generate-sql-load-type=mixed -u root -p
```

…というものです。

なお、途中で EBS の容量が足りなくなるため、

 - 300 スレッド以上 or
 - 8vCPU 以上

の環境では、EBS（gp3）の容量を 200GiB（IOPS:16000）に上げています。

# 結果

インスタンスタイプ     | innodb_log_writer_threads | 150 スレッド | 300 スレッド | 450 スレッド | 600 スレッド
---------------------|:-------------------------:|-------------:|-------------:|-------------:|-------------:
r6g.large(2C16G)     | ON                        | 38.958       | 75.171       | -            | - 
r6g.large(2C16G)     | OFF                       | 35.607       | 69.637       | -            | - 
r5.large(2C16G)      | ON                        | 47.390       | 94.102       | -            | - 
r5.large(2C16G)      | OFF                       | 42.704       | 88.817       | -            | - 
c6g.2xlarge(8C16G)   | ON                        | 21.074       | 38.778       | 60.567       | - 
c6g.2xlarge(8C16G)   | OFF                       | 18.693       | 38.730       | 59.270       | - 
c5.2xlarge(8C16G)    | ON                        | 21.517       | 38.641       | 51.219       | - 
c5.2xlarge(8C16G)    | OFF                       | 17.439       | 33.601       | 49.064       | - 
m6g.8xlarge(32C128G) | ON                        | 23.015       | 38.363       | 60.220       | 78.300 
m6g.8xlarge(32C128G) | OFF                       | 19.396       | 38.636       | 60.055       | 79.811 
m5.8xlarge(32C128G)  | ON                        | 21.009       | 35.220       | 55.962       | 73.508 
m5.8xlarge(32C128G)  | OFF                       | 18.429       | 35.663       | 56.980       | 75.164 

※数値は 3 回実行した平均。単位は秒。g が付くインスタンスタイプが Graviton2 でそれ以外は Intel (x86_64)。(2C16G) は「2vCPU・メモリ 16GiB」を示す。

全てを 1 つの表にまとめてしまったので状況を把握しづらくてすみません…。

## `innodb_log_writer_threads`の ON / OFF

 - 2vCPU 環境では OFF にしたほうが高速化
 - 8vCPU 環境では、スレッド数が少ないと OFF で高速化したが増えていくと差がなくなる
   - ただし Intel プロセッサに限ると OFF で高速化しやすい傾向
 - 32vCPU 環境では、スレッド数が少ないうちは OFF が速いがスレッド数が増えると逆転する

概ね**予想通り**の結果ですね。

## Graviton2 vs Intel (x86_64)

 - 2vCPU 環境では Graviton2 のほうが高速
 - 8vCPU 環境では Intel のほうが高速なケースが多くなる
 - 32vCPU 環境では Intel のほうが高速

vCPU 数が多い環境で Graviton2 の性能が伸びなくなっていますが、今回はソースからコンパイル／ビルドしたわけではなく単純に rpm パッケージをインストールだけですし、実力通りの性能が出ていたのかどうかは判断できません。
あくまでも**「とりあえずやってみた結果」**として受け止めてください。

なお、64-bit Arm（Graviton2）環境で一度だけ`mysqlslap`中に突然 MySQL Server が gone away（再起動）しました。

---

明日（24 日目）は **[Y S（zoosm3）](https://qiita.com/zoosm3)** さんです。

---

**2020/12/26 追記：**

RDS MySQL を使って「追試」してみました。

 - **[RDS Graviton2 インスタンスを試してみた（MySQL 編）](https://qiita.com/hmatsu47/items/bbe1034b078435c31d00)**

---

 - **[Qiitaに投稿したMySQL 8.0関連記事](https://hmatsu47.hatenablog.com/qiita_mysql80)**
 - **[MySQL 8.0 の薄い本](https://github.com/hmatsu47/mysql80_no_usui_hon)（無料で配布中！）**