開発用のMySQL Dockerコンテナのメモリ消費が大きくて辛かったのでperformance_schemaを無効にしてどれくらい減るか調べたメモ

<!--
- 開発用のMySQL Dockerコンテナのメモリ消費を減らすためにperformance_schemaを無効にしてみた
-->

- 開発時に手元のマシンでコンテナを2個、3個と同時に動かさないといけない場面があって辛い
- 特に MySQL 5.6。扱うデータが少量でも 400MB を越える。
    - データちょっとしか入れてないのに？ MySQL ってそういうものなの……？？
- あれこれ調べてパフォーマンススキーマを無効にする方法に辿りついた


<!--
ローカルでの開発に MySQL の Docker コンテナを使っています。
メモリ消費が多くて困っていたので.
投入している初期データが大した量ではないのに 400MB 以上消費しているのは素朴に考えてメモリ使いすぎでは？
みたいな疑問から出発。

どうにか減らせないかと調べて performance_schema の無効化に辿り着きました。

performance_schema を無効にすることの是非は置いておいて（詳しくないので分からない）、とりあえず調べた結果のメモです。
詳しくないので分からないのですが、軽く調べた限りでは、障害の調査やパフォーマンスチューニングに使わないのであれば無効にしても不都合はなさそうでした。
-->

以下、どのくらい減るかを調べたメモです。

※ 無効にして問題ないのかという点については断定を避け（詳しくないので）、この記事では無効にしたときにどのくらいメモリ消費が減るか調べたことについてのみ書きます。ただ、軽く調べた限りでは、障害の調査やパフォーマンスチューニングをしないのであれば、開発用途では無効にしても不都合はなさそうに思えました。


# 結果

※ 以下、"ps" と書いているのは performance_schema の略です。

<!--
パフォーマンススキーマが有効・無効それぞれの場合の
-->

起動した後のメモリ使用量（`docker stats` で表示される値）:

| MySQL のバージョン | ps = ON（MiB）     | ps = OFF（MiB） |
| --- | ---: | ---: |
| 5.6.61 | 464.6 |  59.8 |
| 5.7.34 | 194.3 |  62.7 |
| 8.0.24 | 335.9 | 118.6 |

5.6.61 では無効にすることで 88％減りました :open_mouth:
また、5.7 でパフォーマンススキーマのメモリ消費がかなり改善されたことが分かります。

`show engine performance_schema status` でパフォーマンススキーマ全体でのメモリ使用量を見てみると次のようになっており、上記で減った量とほぼ一致していました。

| MySQL のバージョン | performance_schema.memory (MiB) |
| --- | ---: |
| 5.6.61 | 403.9 |
| 5.7.34 | 131.3 |
| 8.0.24 | 208.4 |



# 調査方法

## 使ったもの

- ホスト: Ubuntu 18.04
- [MySQL の公式 Docker イメージ](https://hub.docker.com/_/mysql)
- [Sakila サンプルデータ](https://dev.mysql.com/doc/sakila/en/)


## ディレクトリ・ファイル配置

```
- (作業用ディレクトリ)
  - sakira-db/
    - 0_sakila-schema.sql
    - 1_sakila-data.sql
  - conf.d/
    - my.cnf
```

`conf.d/` と `sakila-db/` をそれぞれマウントして読み込ませました。下記のスクリプト参照。

## conf.d/my.cnf

```
[mysqld]

# デフォルトでは ON
performance_schema=OFF
```


## 調査用スクリプト


`client.sh`

```bash
#!/bin/bash

CONTAINER_NAME=mysql-sakila

docker exec -it -e MYSQL_PWD=root $CONTAINER_NAME \
  mysql --protocol=tcp -uroot -Dsakila "$@"
```



`restart.sh`

```bash
#!/bin/bash

CONTAINER_NAME=mysql-sakila
TIMEOUT_SEC=120
# MYSQL_VER=5.6.51
# MYSQL_VER=5.7.34
MYSQL_VER=8.0.24

# 動いていたら止める
if (docker ps --format "{{.Names}}" | grep '^'${CONTAINER_NAME}'$' > /dev/null); then
  docker stop $CONTAINER_NAME
fi

# mysqld 起動
docker run --rm -it \
  -e MYSQL_ROOT_PASSWORD=root \
  -v "$(pwd)/conf.d:/etc/mysql/conf.d" \
  -v "$(pwd)/sakila-db:/docker-entrypoint-initdb.d" \
  --name $CONTAINER_NAME \
  -d \
  mysql:$MYSQL_VER

# mysqld の起動完了を待って exit
for i in $(seq $TIMEOUT_SEC); do
  if (./client.sh -e "select 1" > /dev/null 2>&1); then
    printf "\n"
    echo "ok"
    exit 0
  else
    printf "."
    sleep 1
  fi
done

echo "failed"
exit 1
```


`ps_info.sh`

```bash
#!/bin/bash

set -o xtrace

./client.sh -e "
  show variables like 'performance_schema'
"

# パフォーマンススキーマ全体でのメモリ使用量
./client.sh -e "
  show engine performance_schema status
" | grep 'performance_schema.memory'
```

# 参考

- [MySQL :: MySQL 8.0 リファレンスマニュアル :: 27 MySQL パフォーマンススキーマ (dev.mysql.com)](https://dev.mysql.com/doc/refman/8.0/ja/performance-schema.html)
- (2016) [performance_schemaをsysで使い倒す！ | Think IT（シンクイット）](https://thinkit.co.jp/article/10028)
- (2016) [t2.nano で MySQL5.6 を動かすために | ゲンジニア日記](https://blog.yskw.info/articles/295/)
- (2016) [MySQL5.6 performance_schemaとtable_definition_cacheの調整 | riscascape.net](https://www.riscascape.net/archives/7348)