2014年4月4日金曜日

MySQLの新しいInnoDB ページI/O圧縮機能について解析してみた


InnoDBにはデータの圧縮機能がありますが、パフォーマンスが低いことからあまり使われていません。ただ今年の Percona Live で Oracle MySQL, MariaDB, そして Percona Server が新しい InnoDB Compression を出してきました。これはFusion-ioの R&D チームがフラッシュストレージ向けの MySQL 高速化の一環で開発したパッチが元になっています。ちなみに私は Fusion-io の社員ですのでこの発表をワクテカして待っていたのですが、折角コードが一般にリリースされたので、ソースコードを眺めて動作を調べることにしました。

参考にしたのは MySQL Server Snapshots (labs.mysql.com) にあるMySQL with InnoDB PageIO Compression のソースコード、およびMariaDBサイトに掲載された下記ブログ記事などを中心に調べています。

Significant performance boost with new MariaDB page compression on FusionIO

従来の InnoDB の圧縮機能については @sh2nd さんの記事が大変詳しいので、本記事とあわせてお読みになられることをお勧めします。
軽くコードを追っかけただけで実際に動作をトレースなどまではしていませんのでウソを書いていたらごめんなさい。その場合には適宜エントリを修正します。


■ 基本的な動作原理 - 従来の InnoDB 圧縮機能編

従来の InnoDB の圧縮機能は ROW 単位もしくはページ単位で圧縮しています。また、圧縮したデータのブロックサイズは KEY_BLOCK_SIZEで決まりますが、こちらはデフォルトで8KBになっています。16KBのページが1KBに圧縮されたとしても、8KBに、10KBに圧縮されても16KBに繰り上げられるということです。KEY_BLOCK_SIZEを4KBに変更した場合、1KBに圧縮できれば4KB、10KBに圧縮できれば12KBに繰り上げられます。

■ 新たに登場した InnoDB ページI/O圧縮の動作原理

これに対して新しい InnoDB の圧縮機能ではページ単位でまるっと圧縮します。これは InnoDB
のデータ構造のレイヤではなく FIL のレイヤで行われます。つまり InnoDB
エンジン自体は普段圧縮処理をせずに動作し、ファイルの読み書きをするときに透過的に圧縮・展開するイメージです。

次に、新しい InnoDB の圧縮機能で特徴的な点として、ページを圧縮したとしても、そのページには論理的に 16KB の容量が割り当てられたままになります。仮に16KBのページが2000バイトに圧縮できたとしましょう。この時でも、このページに16KBのページサイズが割り当てられたままになります。そして、実際にデータが入っていない部分については fallocate() システムコールによってホールに変換されます。つまり、ファイル中でデータが入っていない部分は「データが存在しない」状態にします。



ホールとなった部分の処理はファイルシステムの動作に依存しますので、ホールをうまく扱えないファイルシステムでは直接のメリットはありませんが、Fusion-ioが開発するNVMFSの場合、スパース空間を作成するとデバイス上では512バイトなどの単位TRIMが行われます。ここで新しいInnoDB の圧縮機能がどう動くかですが
  • 16KB のページをファイルにフラッシュしたい
  • ページを 2000 バイトに圧縮できた
  • ファイルに2KB (512B*4) で圧縮されたページを書き込む
  • 続く14KBにはデータは存在しないため fallocate() システムコールにてホール化
という動作になり、従来 16KB 書き込むシチュエーションで 2KB
のみの書き込みで済むことになります。

この実装の場合、圧縮された InnoDB のデータファイルはスパースとしてそこら中に穴が開いた状態になります。ファイルサイズ 1TB 、メディア上では 500GB の割り当て済みブロックを持つデータファイルを迂闊に cp コマンドなどで操作すると、スパースが解除されて突然大きなファイルに化けたりもするので注意が必要になるでしょう。

ここまで読んでいただいて、すでに気付かれた方もいるかと思いますが、この圧縮機能は、ハードディスクのように「論理ブロックアドレス(LBA)と物理ブロックアドレス
(PBA)の関係が1:1である」デバイス上では意味があまりありません。しかし、内部で追記型の動作をしており、LBAへの書き込みにあわせてPBAがマッピングされるフラッシュストレージ等で利用することを前提に設計された圧縮機能だと言えます。

512バイト単位でピンポイントでデータを書き込むため、ホスト−ストレージ間のデータ転送時間を最小化する意味でも有用です。なぜなら、オーバーヘッドが少ないフラッシュデバイスであれば特に、IOPS性能やレイテンシー性能は、転送バイト数と反比例する関係にあるからです。また、データ量が減ればストレージ容量の有効利用に繋がりますし、フラッシュストレージであれば、フラッシュの寿命が結果的に伸びることになります。 
 


■ でも、ぶっちゃけ、遅いんじゃないの?

いくら高効率な圧縮機能があっても性能が出なかったら仕方ありません。実際のところ性能はちゃんと出るのでしょうか。まだ動かしていないので自分での実測値はもっていないのですが、 MariaDB の下記のブログ記事に性能値の比較がありましたので引用します。
Significant performance boost with new MariaDB page compression on FusionIO

1) TPC-C ライクトランザクション性能の比較

MariaDB で TPC-Cライクなワークロードを1時間流した場合のトランザクション処理量の変化を示したグラフで、横軸が時間、縦軸がトランザクション数の性能値です。なおこの
ベンチマークは TPC-C new order のトランザクション性能に着目しています。
 

青が MySQL uncompressed 、すなわち一般的な InnoDB の圧縮無し状態です。従来の圧縮機能を有効にした場合が赤の値になります。非圧縮で約24000トランザクション/分であった性能値が約4000トランザクション/分程度に落ち込んでおり、オーバーヘッドは83%であることを示しています。

新しい InnoDB のページI/O圧縮の場合の性能値が緑色の線です。こちらは21000トランザクション強/分あたりでほぼ安定しており、オーバーヘッドは10%程度のようです。

2) linkbench でのトランザクション性能比較

赤線が MySQL uncompressed、すなわちベースラインの性能で、緑色が従来のInnoDB圧縮の性能です。

20,000秒時点の性能値で比較すると非圧縮時30,000トランザクション/単位時間であった性能が20,000トランザクション/単位時間程度に落ち込んでおり、このケースでは従来のInnoDB圧縮のオーバーヘッドは33%程度のようです。

新しく実装されたInnoDBページI/O圧縮は青(zlib)および紫(LZ4)です。zlib(青線)の場合は、20,000秒時点約27,500トランザクション/単位時間程度でオーバーヘッドは8〜9%です。LZ4アルゴリズムを利用した場合(紫)は Uncompress時とほとんど性能差が生じていません。余談ですが、先ほどのTPC-Cの性能比較はzlibアルゴリズムを使っていたのかもしれません。

3)InnoDBのデータサイズ比較

最後にデータベースの消費ストレージ容量を比べてみます。これは先ほどの linkbench 実行時のストレージ容量を比較したもののようです。
 

counttable, linktable, nodetable の3つが挙げられていますが、もっとも大きな容量を占める linktable で見た場合、従来のInnoDB圧縮では5割弱の容量削減効果に対し、新しいInnoDBページI/O圧縮では6割程度の容量削減が実現しています。counttable は誤差として無視するとして、 nodetable 含めて考慮するとも全体の圧縮率はもう少し低くなりそうですが、それでも十分な効果だと言えるでしょう。

■ おわりに

InnoDBのページI/O圧縮を使うと、これまで512GBクラスのフラッシュストレージでサイジングしていたシステムであれば、控えめに見積って3割の圧縮効果を期待する場合、358GB程度の容量でよいことになります。逆に、1TB程度のフラッシュであれば1.4TBぶんのデータベースが格納できるようになります。また、書き込み量を 3 割削減できれば、書き換え寿命はその分増加しますから、フラッシュストレージが 1.4 倍長持ちするという事でもあります。

フラッシュストレージは容量単価でみれば高いですから容量効率が高まるのは嬉しいことですし、書き込み量が減少すれば、空き容量が増え、書き込み性能の安定化もつながります。MySQLのInnoDBページI/O圧縮機能は、今後のMySQL+フラッシュの構成に大きな影響をもたらすことは間違いないでしょう。

■長所/短所

長所

  • 512バイトなどのピンポイントでデータを書き込むため、ホスト−ストレージ間のデータ転送時間を最小化できる
  • データベースの容量が小さくなるため、ハードディスクと比べ容量単価が高いフラッシュストレージをより効率的に利用できる
  • 書き込み量を削減できるため、フラッシュの寿命の延命が可能
  • ワークロードとの相性、圧縮アルゴリズムによってはオーバーヘッドが少ない(10%前後)
短所

  • フラッシュ用の実装といえ、ハードディスクには向かない
  • ファイルシステムがフラッシュ上で効率的にスパースを実現できる必要がある

0 件のコメント:

コメントを投稿