OLTP Through the Looking Glass, and What We Found There

http://nms.csail.mit.edu/~stavros/pubs/OLTP_sigmod08.pdf
をちょこっと読んでの感想とか、メモとか。

最初のまとめ

そもそも、OLTPを取り巻く環境はかなり変わっているのに、DBのアーキテクチャは変わってない。新しいデバイスに合わせて、主要コンポーネントの細かいとこまで命令をブレークダウンして、調査した。で、ただプロファイルを取るだけではなくて、機能をとったり、最適化したりすることで、最終的に20xのスループットがでた(TCP-Cで)。どこか一つがボトルネックになっているわけではなくて、ロック、ラッチ、ログ、B-tree、バッファ管理などがそれぞれ重かった。

マシンペックが弱い頃は、トランザクションの並列制御をロックを用いて行っていた。その頃は、OLTPで利用されるデータ量はメインメモリよりも大きかった。ただ、現在は、トランザクションに要する時間は、数マイクロ秒。しかも、比較的安価にメモリを買うことができて、ほとんどメモリにデータベースが乗ってしまう状況になる。ネット上でいろんなサービスがされるに従って、フルスペックのRDBMSでなくともよいというジャンルが出てきた。この界隈では、データベースのようなプロダクトがたくさん出てきた。データベースの代わりとして、

  • ログなしDB:リカバリ時には、別のサーバから情報を貰えば良い。(Harp, Harbor, C-store)
  • シングルスレッドDB:昔は、レイテンシを低くするため、書き込みの待ち時間に違う処理をするため、並列化していた。場合によっては、ひとつのスレッドだけでも十分である場合が出てきた。
  • トランザクションフリー:インターネットサービスでは、eventual consistencyなどのようにトランザクションを考えなくても良い場合がある。また、軽量トランザクションというようなジャンルも受け入れられている( "High Volume Transaction Processing Without Concurrency Control, Two Phase Commit, SQL or C."後で読む。)。これらの条件を、既存のDBに取り入れたらどれほどうまくいくかというのが知りたい。Shoreというオープンな実装に着目し、エンジンのcore部分だけ残したら、640TPS->12700TPSになった。何をしたかというと、ロックフリー、シングルスレッド、リカバリ無しのメインメモリデータベースにした。このことから、Logging,locking,latching(lockingと同じだが、ユーザからは見えないリソース管理に利用),buffer management(ページにアクセスするときのバッファ)を取り除いたら、効果があることが分かった。で、取り除いてみたところ、もとの命令数の6.8%まで下がった。そのために、B-treeの最適化も行っている(Shoreって、聴いたことないと思ったら、1997年に終了しているプロジェクトらしい。結果のグラフはかなり衝撃的、というかまあ、不必要なものを除いたからなのかもしれないけど、本当に必要な機能がなんなのかを突き詰めないとよくわからないものを作ってしまう危険性を感じるね。)。

すでに述べたけど、30年前に比べて、OLTPを取り巻く環境は大きく変わっている。1970では、multi-processで、shared memory。1980では、さらにshared disk。その後20年間で、Gammaをもとにしたような、shared-nothingを対象としてきた。で、最近は、大規模クラスタが対象になってきた。

OLTPの対象とするデータセットは、別にそれほど増えないので、データベースはメモリ上に全部置くことができる。この視点で、以下のような論文が出てきている。

  • Cache Conscious Indexing for Decision-Support in Main Memory(今度軽く読む)
  • Making B+- trees cache conscious in main memory(今度軽く読む)
  • Main Memory Database Systems: An Overview.(今度軽く読む)
シングルスレッド化

メモリ上にデータが乗っかってしまえば、(1)ディスクI/O待ちはなくなり、(2)OLTPではシンプルなクエリしか発行しない、例えば、インデックスをたどって、アップデートなどだが、これは高々数百マイクロ秒で終わる。ということから、マルチスレッド対応にする必要はなくなる。このようなことから、モダンなデータベースでは、ターゲットを分岐している。トランザクション処理とデータウェアハウスです。長い時間を要するうようなクエリは、データウェアハウスの範疇になっている。マルチコアなサーバに対しての対応という意味で、マルチスレッドが必要だと思われるかもしれないが、仮想化すれば、1台であっても複数のshared-nothingのサーバがあると捉えることができる。そして、仮想化環境は必要に応じてリソースを割り当ててくれるだろう。あと、ネットワークが新たなディスクとなって、ボトルネックになるかもしれない。一般的にはそうだが、OLTPの場合には、テーブルを(水平)分割してあげれば、トランザクションは結局単体のサーバ内で完結するだろう。つまり、データベースがターゲットにする分野の中で、ある分野においてはマルチスレッド対応は必要ないだろう。

可用性とログについて

これまでは、REDOログを用いて24x7を実現していたが、スタンバイを用意し、リカバリ時にはスタンバイからデータをu貰って復旧するということがデータウェアハウスでも行われている。ということで、リカバリに関する実装も必要なくなる(うーん、本当にそうなのかな。少なくともActive/standby構成だとちょっと心もとない気がする。standbyに負荷がかかって、おかしくなることがe結構ある気がするんだけど。)

トランザクションの変異

最近利用されている、データストアは、一貫性が弱まっていて、それでもアプリケーションは問題なく動作しているようである。ので、一貫性を保証するためのログやロック、2PCなどは必要性が小さくなる。厳密な一貫性が必要な場合でも、緩和したモデルがある。例えば、広く使われているスナップショット独立は、トランザクションのセマンティクスとスループットトレードオフから考えられた(readのロックを排除したわけですね、別に、完全に新しくなくて良いと。でも、snapshot isolationの文献てどこにあるんだろうか、原典読みたいなあ。)。最近の研究では、機能を大きく削除できるようなセマンティクスも提案されている。例えば、全ての書き込みを行う前に、全てのレコードを読み込んだら、絶対にアボートしないというものである。これにより、UNDOの機能が必要なくなる(うーん何言っているかよくわからない。(“Sinfonia: a new paradigm for building scalable distributed systems"(読みたい)、The End of an Architectural Era (It's Time for a Complete Rewrite)->昔これ読んだ気がするが、こんな話があったけなー。(確認したい))。最終的には、必要のない機能は明示的に利用しないですむようにしたほうが良い(確かにそうだけども、ユーザに設定させるのは難しいよね。)。

さらに少しずつメモ、可読性はないかも

SHOREってのは、モダンなDBMSが持っている機能(WALとリカバリ、2phase-lock(2pcじゃないよ)による並列制御、B-tree)を実装していました。このデータベースは、ライブラリとして提供されて、ログマネージャ、ロックマネージャ、バッファプールマネージャが大きなコンポーネント。これらは、ラッチ(<ー細くまではわかないが、ロック的な物)を用いて、共有のリソースを排他・共有処理する。デッドロックは発見出来ないので、ユーザはデッドロックしないように使う必要がある(本当かなあ?私の読み違いな気がするが、 デッドロックを発見出来ないのは確実)。

あとは、実際に削除した順番と、ベンチマークの結果。特にメモの必要はなさそう。このエントリは、ここまで。この経験をもとにして、H-Storeを始めたんだろうなきっと。次は、H-Storeを見ておきたいな。