Azure Storage:Premium SSDとデータベースとキャッシュ

# 概要

- Azure Storageであるマネージドディスクの特性を調査
- キャッシュなしと読み取り専用キャッシュでIOベンチマークを比較
- キャッシュなしと読み取り専用キャッシュでデータベース処理を比較

# はじめに
Azureにデータベースサーバーを構築するため、どのようなリソースの組み合わせが良いかを検討します。データベースはIOがボトルネックになりやすいのでストレージを重点的に調査します。

# ディスクの種類
Azure Storageの公式サイトを見るとマネージドディスクは4種類あります。データベースサーバーの場合、Premium SSDかUltraディスクが推奨されます。今回はPremium SSDを選択します。
[Azureで利用できるディスクの種類](https://docs.microsoft.com/ja-jp/azure/virtual-machines/disks-types "Azure公式サイトへ")

# Premium SSDで可能なチューニング
#### ディスクサイズ
Premium SSDは容量が大きいほどIOPSが高く設定されています。パフォーマンスを獲得するため、必要以上の容量を確保しなければならない場合があります。
#### ディスクキャッシュ
キャッシュなし、読み取り専用キャッシュ、読み書き用キャッシュの3種類あります。データを格納するのであれば、キャッシュなしか読み取り専用キャッシュの2択になります。
#### ディスクストライピング
複数のディスクでボリュームを構成(RAID0)にすることにより、IOPSを増やすことが可能です。ディスクサイズ同様、パフォーマンスを獲得するため、必要以上の容量を確保しなければならない場合があります。
#### 仮想マシンのサイズ
仮想マシンのサイズによってIOPSの上限が異なります。ディスクサイズ同様、パフォーマンスを獲得するため、必要以上のCPU、メモリーを確保しなければならない場合があります。

[Azure Premium Storage: 高パフォーマンス用に設計する](https://docs.microsoft.com/ja-jp/azure/virtual-machines/premium-storage-performance "Azure公式サイトへ")

# データベース製品固有のベストプラクティス
Azure Storageの公式サイトにはOracleとSQL Serverのベストプラクティスがあります。データベースを格納するディスクはOracleは**キャッシュなし**、SQL Serverは**読み取り専用キャッシュ**が推奨されています。

- 読み取りはデータがキャッシュに乗っていなければ、どちらも同じ
- 書き込みはキャッシュなしの方が若干パフォーマンスに優れる

バッファリングがデータベースの仕事であるなら書き込み能力の優れるキャッシュなしを選択するオラクルのベストプラクティスは理解できます。1回目のデータアクセスはキャッシュに乗っていないはずなので速度は変わらないはずですし、2回目のアクセス以降はデータベースのバッファーに乗るはずなのでキャッシュは関係ないという理屈です。ただし、ページアウトした後の再ページインについてはそんなに長時間キャッシュにデータがあるのかという考えです。他のデータベース製品ならどちらが良いのでしょうか。筆者はDb2のベストプラクティスを知りたいです。
[AzureでのOracleデータベースの設計と実装](https://docs.microsoft.com/ja-jp/azure/virtual-machines/workloads/oracle/oracle-design "Azure公式サイトへ")
[Azure Virtual Machines 上の SQL Server のパフォーマンスに関するガイドライン](https://docs.microsoft.com/ja-jp/azure/azure-sql/virtual-machines/windows/performance-guidelines-best-practices "Azure公式サイトへ")

# 比較する環境
Azureを2環境、vSphereを1環境の合計3環境で比較しました。Azureの違いはデータディスクが**キャッシュなし**か**読み取り専用キャッシュ**かだけで他は同じです。vSphereはオンプレミスで一般的な仮想環境になります。

<dl>
  <dt>Azure-N</dt>
  <dd>Instance DS4v2 (CPU:8 Memory:28GB)</dd>
  <dd>S10 (Standard SSD 128GB     500IOPS)     Cache:ReadWrite OS Disk   </dd>
  <dd>P30 (Premium SSD 1TB  5,000IOPS)×4   <strong>Cache:None Data Disk</strong> </dd>
  <dd>Windows Server 2016</dd>
  <dd>IBM Db2 V11.1</dd>
  <dt>Azure-R</dt>
  <dd>Instance DS4v2 (CPU:8 Memory:28GB)</dd>
  <dd>S10 (Standard SSD 128GB     500IOPS)     Cache:ReadWrite OS Disk   </dd>
  <dd>P30 (Premium SSD 1TB  5,000IOPS)×4   <strong>Cache:ReadOnly Data Disk</strong> </dd>
  <dd>Windows Server 2016</dd>
  <dd>IBM Db2 V11.1</dd>
  <dt>vSphere</dt>
  <dd>VMware vSphere 6 (Xeon E5-2620 Hyper-Threading:on)</dd>
  <dd>SAS共有ストレージ 600GB(15K)×8    RAID6</dd>
  <dd>GuestVM CPU:8vCPU Memory:8GB Disk:1,300GB
  <dd>Windows Server 2012</dd>
  <dd>IBM Db2 V10.5</dd>
</dl>

[SAS:Serial Attached SCSI](https://ja.wikipedia.org/wiki/Serial_Attached_SCSI "ウィキペディアへ")

# IOベンチマーク
[CrystalDiskMark 7](https://crystalmark.info/ "ダウンロードサイトへ")でIOPSを測定しました。Azure-Nがキャッシュなし(None)、Azure-R(ReadOnly)が読み取り専用キャッシュです。Qは待ち行列数、Tはスレッド数になり、Q8T1ですと待ち行列数が8、スレッド数が1になります。

| IOPS     | Azure-N  | Azure-R  | vSphere  | 評価 |
|:--|--:|--:|--:|:-:|                         
| SEQ1M Q8T1 Read   | 372.39   | 257.40   | 656.22   | None > ReadOnly| 
| SEQ1M Q8T1 Write  | 374.34   | 256.38   | 481.45   | None > ReadOnly|
| SEQ1M Q1T1 Read   | 29.40    | 257.39   | 324.54   | **None <<<<<<<< ReadOnly**|
| SEQ1M Q1T1 Write  | 84.01    | 74.40    | 257.02   | None > ReadOnly |
| RND4K Q32T16 Read | 21091.06 | 32970.70 | 39069.82 | None < ReadOnly |
| RND4K Q32T16 Write| 20510.50 | 22403.81 | 20116.46 | None < ReadOnly |
| RND4K Q1T1 Read   | 100.59   | 11454.35 | 4499.27  | **None <^112< ReadOnly** |
| RND4K Q1T1 Write  | 440.43   | 415.04   | 2324.71  | None > ReadOnly |


**キャッシュなし(Azure-N(None))**と**読み取り専用キャッシュ(Azure-R(ReadOnly))**を比較し、2倍以上の差がついたものを太字にしています。SEQ1M Q8T1はRead、Writeともキャッシュなしが僅差で勝っています。SEQ1M Q1T1 Readは**8倍の差**、RND4K Q1T1 Readは**113倍の差**で**読み取り専用キャッシュが勝っています**。スループットの結果も同じでした。

<details><summary>スループットの詳細</summary><div>

| MB/s              | Azure-N | Azure-R  | vSphere  | 評価 |
|:--|--:|--:|--:|:-:|                         
| SEQ1M Q8T1 Read   | 390.475 | 269.91 | 688.096 | None > ReadOnly| 
| SEQ1M Q8T1 Write  | 392.526 | 268.83 | 504.839 | None > ReadOnly|
| SEQ1M Q1T1 Read   | 30.830  | 269.89 | 340.300 | **None <<<<<<<< ReadOnly**|
| SEQ1M Q1T1 Write  | 88.094  | 78.01  | 269.500 | None > ReadOnly |
| RND4K Q32T16 Read | 86.389  | 135.05 | 160.030 | None < ReadOnly |
| RND4K Q32T16 Write| 84.011  | 91.77  | 82.397  | None < ReadOnly |
| RND4K Q1T1 Read   | 0.412   | 46.92  | 18.429  | **None <^112< ReadOnly**  |
| RND4K Q1T1 Write  | 1.804   | 1.70   | 9.522   | None > ReadOnly |

</div></details>

# データベースでのパフォーマンスの違い
データベースはDb2を使用しています。OLTPアプリは対話型で照会の割合が多いものを人間が操作して評価しています。数値による評価ではなく申し訳ないです。インポートは274個のテーブルをファイルから取り込む時間を計測しています。
[OLTP:Online Transaction Processing](https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E5%87%A6%E7%90%86 "ウィキペディアへ")

|      | Azure-N  | Azure-R  | vSphere  | 評価 |
|:--:|:--:|:--:|:--:|:-:|                         
| OLTPアプリ  | 体感するほど遅い | vSphereと同じ   | 普通   | None < ReadOnly| 
| インポート  | 47分   | 10分   | 6分   | **None <<<< ReadOnly** |

どちらも読み取り専用キャッシュ(Azure-R(ReadOnly))の方が速いという結果になりました。OLTPアプリは負荷をかけていない状態でも明らかに速度が違うのでIOPSのランダムQ1T1Readの差が出ていると思います。インポートはファイルから読み込む処理なのでシーケンシャルQ1T1Readの差が**4倍**という数字に表れていると思います。

# まとめ
#### 評価
Db2の場合、読み取り専用キャッシュの方がパフォーマンスに優れるという結果になりました。
#### 疑問点
理屈で考えると、キャッシュはデータが乗ってから速くなるのでキャッシュに乗っていない1回目のアクセスはどちらも速度は変わらないはずです。特にインポートはテストもキャッシュなしを計測した後にキャッシュありに切り替えているので、読み取り専用キャッシュの計測はキャッシュにデータが乗っていない状態です。インポート処理の速度に違いが出るのをどう説明すればいいのでしょうか。
#### Azure Storage公式
公式には「読み取りキャッシュは、**一連の順次読み取りのように、読み取りキューに対して何らかの予測可能性がある場合に役立つ点に留意**してください。 ランダム I/O の場合、アクセスしているデータがストレージ全体に分散しているため、キャッシュのメリットはほとんどないかまったくありません。さらに、ディスクのパフォーマンスが低下する可能性があります。」とあります。
[Azure portal を使用して Azure VM ディスク キャッシュを有効化して構成する](https://docs.microsoft.com/ja-jp/learn/modules/caching-and-performance-azure-storage-and-disks/3-enable-and-configure-azure-vm-disk-cache-by-using-the-azure-portal "Azure公式サイトへ")
#### 考察
インポートはファイルから読み取るシーケンシャル処理ですので先読みが可能になります。これにより読み取り専用キャッシュは先回りしてあらかじめデータをキャッシュに乗せていると考えられます。読み取り専用キャッシュがランダムアクセスするはずのOLTPアプリにも効果があるのがなぜなのか、疑問に残ります。

# 次回
AzureとvSphereのIO速度を比較し、Azureの苦手な処理をデータベースでどうするかを考えます。
[Azure Premium SSD はシングルスレッド書き込みが苦手？](https://qiita.com/tsunenorikan/items/87088a767af69faecd0d "Qiita")