CloudSQLのIO性能を観察する（検証編）


# 概要

[前回](https://qiita.com/mokrai/items/19fb9c0564e9a75cd589)の続き。ディスクサイズが50GB, 100GB, 200GB, 400GB, 600GBのパターンで、それぞれ負荷をかけてIO性能を観察する。

負荷のかけ方は、MySQLの`LOAD DATA LOCAL INFILE`で巨大なデータを読み込ませる。

# 結論
一つ一つの検証結果の前に、結論を書いておく。

* ディスクサイズを増やすと、IO性能はその増加率に近い割合で向上した
    * ディスクサイズを２倍にすると、IO性能（IOPS, スループット）は約1.8倍になった
    * ただし、一定以上はIO性能が伸びなくなったため、ボトルネックが別の箇所に移ったと思われる
        * CPU、メモリ、NWのいずれも頭打ちになっている様子は見えないので、MySQL内部の可能性が高い
* ディスクサイズから計算されるIO性能と実際に出ている性能が一致しない
    * 「実際に出ている性能」とは、Stackdriverのメトリクスから取得したもの。これを正しく理解できていない可能性もある
* ディスクサイズの選択は、必要なディスク領域によって決めがちだが、必要なIO性能という観点でも考えた方がいい
    * SSDの場合、ストレージ料金は\$0.22/month。例えば、50GBから100GBにディスクサイズを増やしたとき、\$11/monthの追加コストでIO性能を倍にできる


# 環境（共通）
* CloudSQL
    * MySQL 第 2 世代
    * MySQL 5.7
    * ストレージの種類:SSD
* クライアント
    * ComputeEngine
    * Debian GNU/Linux 9
    * vCPU x 2、メモリ 7.5 GB
* 検証データ
    * 31GB（CSVファイル）、43GB（MySQLテーブル）、31,017,889行



# 検証

[table_load.sh](https://qiita.com/mokrai/items/19fb9c0564e9a75cd589)を実行した。

検証によっては、２つのプロセスからこのスクリプトを実行している。（テーブルは別のテーブルにロード）

## パターン1

CloudSQLの設定が下記。スループットとIOPSは、ディスクサイズによって決まる最大の値。（GCPのWebUIから確認可能。CloudSQL->インスタンスを選択->編集->ディスクの設定のところ）

|vCPU|メモリ|ディスクサイズ|読み取りスループット(MB/秒)|書き込みスループット(MB/秒)|読み取り IOPS|書き込み IOPS|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|2|7.5 GB|50GB|24.0|24.0|1500|1500|


### 結果
Stackdriverのメトリクスから取得した結果をまとめる。

|項目|値|
|:-:|:-:|
|所要時間|１時間20分|
|WriteOperations|600/sで安定。終了直前だけ、862/sというスパイクが見られた。|
|InnoDB pages written|480/s前後で安定。終了直前だけ、770/sというスパイクが見られた。|
|書き込み量|7.5 MB/s(16384 * 480  / 1024 / 1024) innodb_page_sizeから推定。
|Network Bytes Received By MySQL|6.3 MB/sで前後で安定|
|CPU Utilization|60%前後で安定|

#### クライアント側
何かがボトルネックになっている様子はない。

## パターン2
二つのプロセスからデータをロード。テーブル名はそれぞれ変える。

### 結果
ほぼパターン１と変わらず。念のためクライアントとMySQLのスケールをアップしたが、IO性能は変わらず。

## パターン3

ディスクサイズを２倍に増やした。

|vCPU|メモリ|ディスクサイズ|読み取りスループット(MB/秒)|書き込みスループット(MB/秒)|読み取り IOPS|書き込み IOPS|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|2|7.5 GB|100GB|48.0|48.0|3000|3000|

### 結果
#### CloudSQL

|項目|値|
|:-:|:-:|
|WriteOperations|1080/s前後で安定|
|InnoDB pages written|860/s前後で安定|
|書き込み量|13.4375 MB/s(16384 * 860  / 1024 / 1024) innodb_page_sizeから推定。
|Network Bytes Received By MySQL|11 MB/s前後で安定|
|CPU Utilization|60%前後で安定|

IOPS(WriteOperations)、スループット（１秒あたりの書き込み量）ともにディスクサイズを増やす前の1.8倍になった。
ディスクの増加率（２倍）と同じにはならなかったが、IO性能の向上が見られた。

## パターン4

二つのプロセスから、異なるテーブルにデータをロードする。

### 結果
パターン3とIO関連のメトリクスについては変わらず。CPU使用率が少し増え約65%。

## パターン5
ディスクサイズを２倍に増やした。

|vCPU|メモリ|ディスクサイズ|読み取りスループット(MB/秒)|書き込みスループット(MB/秒)|読み取り IOPS|書き込み IOPS|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|2|7.5 GB|200GB|96.0|96.0|6000|6000|

### 結果

|項目|値|
|:-:|:-:|
|WriteOperations|2000/s前後で安定|
|InnoDB pages written|1600/s前後で安定|
|書き込み量|25 MB/s(16384 * 1600 / 1024 / 1024) innodb_page_sizeから推定。
|Network Bytes Received By MySQL|21 MB/s前後で安定|
|CPU Utilization|60%前後で安定|

IOPS(WriteOperations)、スループット（１秒あたりの書き込み量）ともに約1.85倍になった。

## パターン6
ディスクサイズを２倍に増やした。

|vCPU|メモリ|ディスクサイズ|読み取りスループット(MB/秒)|書き込みスループット(MB/秒)|読み取り IOPS|書き込み IOPS|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|2|7.5 GB|400GB|192.0|151.5|12,000|12,000|

### 結果

|項目|値|
|:-:|:-:|
|WriteOperations|2500/s弱で安定|
|InnoDB pages written|2000/s前後で安定|
|書き込み量|31.25 MB/s(16384 * 2000 / 1024 / 1024) innodb_page_sizeから推定。
|Network Bytes Received By MySQL|26 MB/s前後で安定|
|CPU Utilization|60%前後で安定|

ディスクサイズを２倍にしたが、IO性能は1.25倍にとどまった。

## パターン7
パターン6と同じ環境で、２つのプロセスからデータをロードする。

### 結果

|項目|値|
|:-:|:-:|
|WriteOperations|2800/s弱で安定|
|InnoDB pages written|2200/s前後で安定|
|書き込み量|34.375 MB/s(16384 * 2000 / 1024 / 1024) innodb_page_sizeから推定。
|Network Bytes Received By MySQL|29 MB/sで安定|
|CPU Utilization|77~79%|

パターン6よりはIO性能が上昇したが、パターン4の2倍にはならなかった。（約1.4倍）


## パターン8
ディスクサイズをさらに増やして、600GBにする。

|vCPU|メモリ|ディスクサイズ|読み取りスループット(MB/秒)|書き込みスループット(MB/秒)|読み取り IOPS|書き込み IOPS|
|:--:|:--:|:--:|:--:|:--:|:--:|:--:|:--:|
|2|7.5 GB|600GB|288.0|151.5|15,000|15,000|

### 結果

パターン6とほぼ同じ結果だった。つまり、ボトルネックがIOから別のところへ移ったといえそう。


# メモ
### 書き込み量を推定

"InnoDB pages written" × "innodb_page_size"で推定可能。
"InnoDB pages written"はStackdriverから取得可能。"innodb_page_size"は、`show variables;`から取得可能。

# 参考資料

* ブロック ストレージのパフォーマンスの比較
    * https://cloud.google.com/compute/docs/disks/performance?hl=ja#type_comparison
* Cloud SQL 第 2 世代のパフォーマンスと機能を詳説
    * https://cloudplatform-jp.googleblog.com/2016/08/cloud-sql-2.html
* Stackdriverのメトリクスについて
    * https://cloud.google.com/monitoring/api/metrics_gcp#gcp-cloudsql
* CloudSQL　ストレージの料金
    * https://cloud.google.com/sql/docs/mysql/pricing?hl=ja#2nd-gen-storage-networking-prices