MySQLのMyRocksストレージエンジンの話を中の人から聞いた

この記事は[freee Engineers Advent Calendar 2016](http://qiita.com/advent-calendar/2016/freee)の...っと、**もう空きがない**じゃないか!
というわけで、急遽[MySQL Casual Advent Calendar 2016](http://qiita.com/advent-calendar/2016/mysql-casual)の16日目としてお送りします。

MySQLエキスパートであるところのFacebook 松信嘉範さんによるMyRocks紹介プレゼンを聞く機会に恵まれたので、本人の許可を得てその内容を公開します。

# 経緯
松信さんと自分は以前に同じ会社で働いていた元同僚で、彼のデビュー作「[現場で使える MySQL](http://amzn.to/2hyrtqs)」の元となったDBマガジンの連載時にちょっとお手伝いした縁もあり、その後も交流が続いております。

今回は松信さんがちょいと日本に寄るというので食事に誘ったのですが、ついでなので私の現職 [freee株式会社](https://www.freee.co.jp/)のオフィス見学に来てもらい、「**せっかくだから何かしゃべって**」という図々しいお願いをしたところ、freee社員限定のMyRocksプライベートセミナーという贅沢企画が実現することになりました。

以下、社内メモからの転載なので、雑な表現とか乏しい内容とかはご容赦ください。

あと、細かいところは松信さん自身による記事
[MyRocks: A space- and write-optimized MySQL database](https://code.facebook.com/posts/190251048047090/myrocks-a-space-and-write-optimized-mysql-database/)や、[MyRocks Deep Dive](http://www.slideshare.net/matsunobu/myrocks-deep-dive)を参照してください。

# FacebookにおけるMySQLの使い方の特徴
ソーシャルグラフ情報を大量のDBに分散して格納。

前段にキャッシュを置いているが、それにヒットしないとMySQLにクエリーが来る。
これを高速にさばけないとユーザー体験に影響する。
レスポンスの目安は1ミリ秒。

運用は自動化できるところは自動化して、Production Engineer(運用エンジニア)の負担を減らす努力をしている。

# MySQL(InnoDB)に関する悩み
## 領域効率
MySQLの物理ストレージはほとんどフラッシュストレージ(SSD)で、HDDはほんの一部。
フラッシュは高価なので、なるべく高い格納効率を実現したい。

特にB+Treeインデックスはフラグメンテーションが発生しやすいので、領域の実効効率は50%くらいまで低下したりもする。

InnoDBには[圧縮機能](https://dev.mysql.com/doc/refman/5.6/ja/innodb-compression.html)があるし、圧縮関連の独自のパッチを当てたりもしているが、それでも領域が劇的に減ったりはしない。

圧縮データは[KEY_BLOCK_SIZEで指定される固定のブロックサイズで保存される](https://dev.mysql.com/doc/refman/5.6/ja/innodb-compression-background.html)が、例えばそれを8KBにしたとすると、圧縮後サイズが8KB以下になっても結局8KBは消費されるので(Compression Alignment)、圧縮できた分がそのまま消費領域の減少にはつながらない。

## 書き込み量
キャッシュを活用しているため、Read/Write比率は一般的なユースケースよりもWriteがかなり高い(5%とか10%とかではない)。
フラッシュには書き込み可能回数の制限があるので、書き込み量/回数をできるだけ減らしたい。

しかしInnoDBだとほんの数バイトの更新であってもページ全体の書き込みになるので、この点でFacebookにとってInnoDBはベストな選択肢とは言えない。

# そこでMyRocks
MyRocksとはFacebookで開発しているMySQLストレージエンジン。
Key-Value Storeの[RocksDB](https://github.com/facebook/rocksdb)を、MySQLのストレージエンジン化した。

RocksDBは[LSM Database](https://en.wikipedia.org/wiki/Log-structured_merge-tree)の一種。
Googleの[LevelDB](https://github.com/google/leveldb)をforkした。

扱いやすく圧縮効率が高い。
実データに対するオーバーヘッドは10%くらいに収まる。
また、書き込み効率も良好。

そんなRocksDBをMySQLで使うために開発したのがMyRocks。
2年くらい前から取り組みを開始して、検証を行い効果を確認した後、最近になってプロダクション環境にも適用し始めた。

# 性能評価結果
評価観点はDBサイズ、書き込み量に加えて、性能。
いくら2つの課題を解決しても性能が悪かったら元も子もない。

## DBサイズ
![database_size.jpg](https://qiita-image-store.s3.amazonaws.com/0/19683/79c3461e-65fb-aeb8-4186-932b5d7c6105.jpeg)

*著者本人の許可を得て [MyRocks: A space- and write-optimized MySQL database](https://code.facebook.com/posts/190251048047090/myrocks-a-space-and-write-optimized-mysql-database/) から転載(以下同じ)*

圧縮したInnoDBに比べて**約半分！**
圧縮前と比べるとなんと**約30%!**

なおページサイズ１６KB、KEY_BLOCK_SIZE=8KBなので、InnoDBの圧縮の効果がCompression Alignmentにより4割減程度と、半分以下にはならないこともこの結果から分かる。

## 性能
![queries_per_second.jpg](https://qiita-image-store.s3.amazonaws.com/0/19683/d0a2bca4-1b76-a98a-423d-3a9cf897b27b.jpeg)

Facebookのユースケースに合わせて高いWrite比率を前提としているが、InnoDBより高いTPSが出ていることが分かる。

もしWrite比率が低くなればInnoDBの性能のほうが良くなるだろう、とのこと。

## 書き込み量
![write_amplification.jpg](https://qiita-image-store.s3.amazonaws.com/0/19683/dd8fa9b5-3b64-5fa4-9f65-96b6fb2a8e27.jpeg)

**激減!**
すごい。

# MyRocksの入手方法
MyRocksはオープンソース。
FacebookのGithubレポジトリで公開されている[Facebook版MySQL](https://github.com/facebook/mysql-5.6)の中に入っているので、これをダウンロードしてビルドする。

または[MariaDBで利用することもできる](https://mariadb.com/resources/blog/facebook-myrocks-mariadb)し、[PerconaがDockerイメージを配布](https://www.percona.com/blog/2016/09/06/myrocks-docker-images/)しているので、これからの本格普及を期待している。

これらのディストリビューションに含まれる主な機能。

* オンラインバックアップ
    * mysqldumpによる論理バックアップ
    * myrocks_hotbackupによるバイナリバックアップ
* トランザクション
* 再構築なしでのスレーブのリカバリ

# InnoDB→MyRocks移行
ダウンタイムなし、リーズナブルな時間でイケる。

InnoDBスレーブとMyRocksスレーブを作り、両者で同一性を検証するOnline Data Verificationもできる。

# MyRocksをプロダクション適用した効果
**ストレージ容量50%削減！**
**サーバー台数も50%削減!**

もっとも1台あたりのストレージ容量が半分になったから単純に2台を1台にできたわけではない。
1台あたりでさばくトランザクション数は倍になるので、CPUやメモリには余裕がないといけない。

今後もストレージ容量がボトルネックになってるところを中心に適用を拡大していく。
InnoDBに適性のある処理もあるので、全部をMyRocksに置き換えるわけではない。

# これからやること
* MyRocksの適用範囲の拡大
* Online DDL
* Foreign Keys
* ドキュメント

# 僕はこう思ったっす
MyRocksってすごいですね。(小並感)

freeeもMySQLユーザーですがAmazon RDSベースなので、残念ながらすぐには使えません。
今後の機能改善と相まってユーザー数とニーズが伸び、RDSでもサポートされるといいな!

という期待を込め、少しでもMyRocksの普及に貢献できれば! という思いで、この記事をお送りいたしました。

(いや、会社が成長して、RDSに頼る必要のないレベルのデータベースチームが編成されるとかでもいいのか)

# おまけ
## 乙ちゃん
その後、松信くんとタクシーで向かったのは鮫洲にある[乙ちゃん](https://tabelog.com/tokyo/A1315/A131501/13154344/)という焼肉屋。
いま東京で食うべき焼肉ランキング、俺的ナンバーワン。

![otochan.jpg](https://qiita-image-store.s3.amazonaws.com/0/19683/271432df-4b31-f987-3a4f-bc3ce5a5424a.jpeg)

肉は写真の極上盛り合わせ(８００ｇ 8000円くらい)に加えて、単品で何皿か。

メンバーは元同僚がさらに2人合流しての計4人で、食って飲んで1人あたり約5000円のコストパフォーマンス!

## 寿司 しながわ 葵
2軒目は青物横丁の[寿司 しながわ 葵](https://tabelog.com/tokyo/A1315/A131501/13179434/)。

店主は六本木ヒルズ グランドハイアット東京の高級寿司店 [六緑](https://tabelog.com/tokyo/A1307/A130701/13018973/)で副料理長まで務めた腕利きの職人で、子どもの学校つながりのパパ友。
2年前に開いたこのお店では、六本木に比べて大変リーズナブルな価格で最高級の料理が楽しめる。

それなりに腹は満たされていたのでつまみをお任せで出してもらいつつ日本酒をいただく。

どの料理も丁寧かつ凝った細工で、味も絶品。
食べていたら食欲が湧いてきて、結局最後に寿司を3貫いただいてしまった。

![IMG_1288.JPG](https://qiita-image-store.s3.amazonaws.com/0/19683/131ea874-e055-bf0f-067c-26d5d6080401.jpeg)

これは別の日にいただいたランチメニューのバラチラシ。

お近くにお住まい・お勤めの皆さま、ぜひご贔屓にどうぞ!
お座敷個室もありますが、オススメはカウンター席。
ネタケースがないので、プロの包丁使いが間近で見られます。
これはもはやショー！
海外からのゲストには特に喜ばれます。