リレーショナルデータベース技術の遷移の歴史(勝手に整理)

RDBMSについては,2004年2月くらいからいろいろ見てきたわけだけど,自分の中でかなりざっくり整理がついてきた.全部ちゃんと説明すると,本1冊文くらいになってしまう(当然)ので,evidenceは抜きにして結論だけ記述します.

過去に書いた日記に手がかりが書いてあったりすると思うのだけど,もし良くわからんけど興味ありという方がいたら気軽にコメントして下さい.(どれくらいの方に見ていただいているか不明だけど)

                                                                                                                                                • -

【前置き】
RDBMS世界に,これまで3回の津波のような強い影響のあるアーキテクチャ的進化があった.それは,RDBMSのコンセプトと実装技術と高度化によるものでもあり,またソフトウェア開発基盤の進化によるものでもあり,またシステム構築に関する考え方のパラダイムシフトによるものでもある.

                                                                                                                                                • -

RDBMS第一の波:ロックによる同時実行制御からマルチバージョニング同時実行制御へ】
恐らく,1990年代前半から後半にかけて.ANSI標準SQL1992が定義された1992年当時には,複数トランザクションの同時実行制御を行うためには,ロックを用いるのが常識と考えられていた.DB2Microsoft SQL ServerOracleどれもロックによる同時実行制御を行っていた.

Oracleの内部設計を知らないので断言できないが,どこかのタイミングで,Oracleはマルチバージョニングによる同時実行制御の実装にシフトした.うわさではOracle6とか7でかなり大掛かりな作り直しを行って性能が急激に改善したとのこと.たぶんそれはマルチバージョニングによるもの.あと,ロック数の無制限化.

ロックをどのように実装するかというのはRDBMSの最も重要な要素の一つで,究極的には,ビットマップと呼ばれる,0 or 1 (この行はロックされている/いない)といった,1行につき1ビットの情報量のみでロックを管理する実装に到達する.(共有/排他ロックそれぞれに1ビット.)これによりロック数は事実上,無制限化する.

「どのセッションがどのテーブル/行をロックしている」と言う風な情報を,ロックを中央制御するようなモジュールで管理しているタイプだと,1回ロックを行うために数十バイトの領域が必要となり,ロック数には上限がでてくる.上限を超えないようにRDBMSがエラーを返す仕様にするか,ロックエスカレーション機能を実装するかしかなくなり,どっちにしてもアーキテクチャ的に0点となる.

関連性を解明しきっているわけじゃないのだけれども,ロックをビットマップで管理できているRDBMSは,マルチバージョニング同時実行制御も容易に実装できるので,実装している.

マルチバージョニングとは,論理的には1つの行に対して,物理的には複数のバージョン(コミットされるごとに異なるバージョン)を持てるようにして,SelectとUpdateの同時実行性能を著しく高めることができるようにする仕組み.

ビットマップによるロックの管理とマルチバージョニング同時実行制御を実装できているか否かで,RDBMSの性能が大きく差が出る.ここが一つ目のポイント.

達成済みのRDBMSの例 = Oracle, MySQL, PostgreSQL
未達成のRDBMSの例 = DB2 UDB, Microsoft SQLServer

DB2はStingerでリードロック検出機能(エラーを返すようにする)を実装することで,リードロックの弊害をアプリケーション開発者が低減できるように改善しているが,ストレージエンジン自体の改良が行われていないため,焼け石に水

SQLServerは,元々"readpast"という読み取りオプションを用意し,リードロックを検知するとその行をスキップするという方法によってリードロック回避法が実装されているが,行をskipしたのかどうかは取得できないので,使い道は少ないと思われる.次期バージョンのYukonでは,擬似マルチバージョニング機能を実装するが,これもやはりストレージエンジン自体の改良ではなく,マネジメント・モジュールの機能拡張で行ってるっぽいので,焼け石に水

どちらも,ストレージエンジンの改良に着手されることを望む.

                                                                                                                                                • -

RDBMS第二の波:マルチプロセスからマルチスレッドへ】
たぶん1990年代後半から2000年代にかけて.RDBMSは巨大なソフトウェアであるため,当然,一つのプログラムのみで動いていては全く性能が出ない.

REDOログを出すプログラム,セッションを管理するプログラム,検索処理を実行するプログラムなど,複数のプログラムが同時並行的に動くことで,一つのみで動作した場合にパフォーマンスの低下の原因となるファイルI/Oやユーザ入力待ち,複数ユーザアクセス制御などをかなり無害化できる.

プロセスとは,プログラムの実行状態を指す概念であり,OSからは3つのリソースを独立して与えられる.「CPU時間」「メモリ空間」「ファイルやネットワークのI/O」である.「共有メモリ」などの特殊なリソースは別として,プロセスがOSから与えられるリソースは互いに排他的である.(というか別プログラム同士なんだから,一緒じゃ困る.あたりまえ.)

しかしソフトウェアの性能を引き出すためにマルチプロセスを用いるとなると,排他的では困る場合がある.「共有メモリ」を使わないとデータ共有ができない.それ以外の手としては,ソケット等によるプロセス間通信を行う必要がある.まずこの部分にオーバーヘッドがある.

次に,プロセスの起動は重いという特徴がある.クライアントからの接続要求がある度にプロセスを起動する,というような利用法は,本来の「プロセス」では想定されていないのである.

つまり,並行処理を行って性能を向上させるという目的でマルチプロセスを使った場合,プロセス自体の特性によって,思惑が上手くいかなくなるということになる.そこで「並行処理をしたい」という要求に純粋に答えるものとして,スレッド(ライトウェイトプロセス)がOS側に実装された.スレッドとは,親となるプロセスを元に起動されるもので(プロセスなしにスレッドの起動は無い),そのプロセスと「メモリ空間」「ファイルやネットワークのI/O」は共有し「CPU時間」については独自に与えられるようになったものである.

さて,このようにしてスレッドが登場したわけだから,ソフトウェアも並行処理による性能向上を行う場合には,マルチプロセスではなくマルチスレッドを用いるほうが,本来の目的にも適合し,良い効果を得ることができるということになる.

そこで,多くのソフトウェア(特に新規に作られたソフトウェア)で,マルチスレッド対応が行われた.Javaが基本的にマルチスレッドであり,J2EEサーバのWEBコンテナもマルチスレッドでリクエストを処理するのは,この原則に乗っている.

しかしRDBMSの世界では,この時点で既にかなり重量級のマルチプロセスプログラムによる実装が行われており,マルチスレッドを用いたアーキテクチャへ移行することが非常にコストのかかる困難な要件となってしまっていた.比較的新しいRDBMS(変更コストが少ない)で,オープンソースRDBMS(開発改良が速い)では十分なマルチスレッド対応が行われたが,それ以外のRDBMSではいまだに十分なマルチスレッド対応が行われていない.

マルチスレッド対応済みRDBMS = MySQL
マルチスレッド対応不十分なRDBMS = Oracle, PostgreSQL

(DB2SQLServerについては評価中)

特に,PostgreSQLは,オープンソースソフトウェアでありながら,マルチスレッド対応がかなり遅れているように見受けられる.新しい接続要求を処理するたびに,fork()していては駄目.

OraclePostgreSQLも,早急な改善が望まれる.

                                                                                                                                                • -

RDBMS第三の波:スケールアップからスケールアウトへ】
たぶん2000年代から.システムを単に構築する,というだけでなく,その後運用してしばらくした後,拡張するというケースは多い.その際に採られる手法として存在するのがこの「スケールアップ」と「スケールアウト」である.

システムの拡張といった場合,さまざまなケースが存在するだろう.機能を追加するといった拡張もあるが,話を単純に留めておくため,特にソフトウェア面での増強は行わないものと仮定する.同じシステムに対して,ハードウェアリソースを追加して「リクエストが増えたので処理性能を高めたい」「システムの重要度が増しているので,ダウンしないように可用性を高めたい」といった要求に答えることができるようにするものとする.

これらに対して,従来から最も採用されてきた手法が「スケールアップ」だ.スケールアップとは,例えばサーバのメモリ容量を追加する,高い周波数のCPUに置き換える/CPUを追加するといったことによって,そのサーバのハードウェアとしての性能を高めて対処する方法を指す.可用性については,より高価なメモリ(高機能なエラー検出機能つき)を採用したり,可用性を高めるための専用のハードウェアを用いたりする方法がある.

ハードウェア,ソフトウェア,サポート体制の全てをそのように費用を投じて一つの筐体の性能(特に可用性)を高めていたのがメインフレームだったのであるわけだが,ダウンサイジングとオープン化の流れを受けて徐々にメインフレームが後退していったのと同様に,スケールアップ手法も後退を始めていった.なぜなら,費用対効果で見た場合,現在のメインフレームと同様,スケールアップは非常に費用のかかる手法であったからである.

スケールアップを後退させたのが,スケールアウトという新しい考え方である.スケールアウトの考え方では,一つのサーバ筐体を強化するというのではなく,手ごろな値段のサーバ筐体を複数用意してそれらを並行運用させることで,処理性能や可用性の向上を図る.

複数のサーバ筐体にそれぞれ配備されているソフトウェアを連携させる必要があるので,ソフトウェア的な新しい仕掛けが必要となるが,スケールアップの時にやっていたようなハードウェア的な対応と比べると,柔軟性と費用の点で勝る.(少なくとも今日時点までは,ソフトウェアで実装できるものはハードウェアでなくソフトウェアで実装したほうが効率面・経済面で勝っている.)

従って,RDBMSの世界でも,性能向上のための手段として,スケールアウトにどれくらい対応できているかが重要となってくる.RDBMSの場合,ずばりクラスタリング等の負荷分散・高可用性ソリューションがテーマとなってくるわけであるが,またそこの部分を見てみると,各RDBMSそれぞれ違いがある.

例えば,クラスタリングには大きく分けて2つの方法があるのをご存知だろうか.一つは「シェアードディスク方式」という方法である.これは,RDBMSなどの各ソフトウェアは別々のサーバ筐体で動作させるが,記憶媒体としてのハードディスクは,「共有ディスク」と呼ばれる特別で高価なハードウェアを使用する方法である.シェアードディスク方式は,この例からも分かるように,スケールアウトよりはスケールアップに近い考え方のクラスタリングである.

一方「シェアードナッシング方式」というクラスタリングでは,共有ディスクのような特別で高価なハードウェアは不要である.本当に通常のレベルの値段のサーバ筐体(場合によっては秋葉原で買えるPCサーバでも可)を複数用意するだけでよく,その分クラスタリング用のソフトウェアががんばることになるが,シェアードナッシング方式はまさにスケールアウトの考えに立つクラスタリングである.

RDBMSをこの点で評価する場合,まずそれぞれのクラスタソリューションがどの程度「シェアードナッシング」なのかで見ることができる.もっとよく見るには,レプリケーションなどの簡易クラスタリング機能が,どれだけシンプルに設計実装されているかをチェックすると良い.スケールアウトに対応しているRDBMSほど,そこ部分もシンプルになっている.レプリケーションはそういう意味では良い指標となっていて,レプリケーションの設計と実装が複雑になっているRDBMSは,おおよそスケールアウトへの対応もかなり遅れている.

また,パフォーマンスチューニングについての考え方にも,違いが出てきているのでそこを見ることでも評価できる.メモリやCPUを大量に与えた場合にどのようにチューニングすべきかというようなことに重点をおいているRDBMSは,スケールアップ的である.逆に,レプリケーションを使ったスケールアウトによって簡単に処理性能や可用性を向上させることができるRDBMSはスケールアウト的である.

スケールアウト対応済みRDBMS = MySQL
スケールアウト対応が遅れているRDBMS = Oracle

(他のRDBMSについては評価中)

                                                                                                                                                    • -

【総合評価】
Java系エンジニアの方は,J2EEサーバの世界で,最初はJBossの独自アーキテクチャに過ぎなかったJMXマイクロカーネルカーネルアーキテクチャが,その評価を得ていく中で,次第にデファクトスタンダードを獲得したのを思い起こして欲しい.各プロダクトのコアなアーキテクチャというのには,完全に独自のアーキテクチャに過ぎないものと,広く一般にその効用が認められて,業界全体に時代進化的な影響をもたらすアーキテクチャというのがある.

今回挙げた3つのRDBMSについての技術は,まさにそういったポイントとなるアーキテクチャだと思っている.私の評価では,DB2Microsoft SQLServerは既にマルチバージョニングの時点でこのRDBMS技術競争の先頭グループから脱落してしまっている.マルチスレッドとスケールアウトについてはMySQLさらにOraclePostgreSQLを引き離して独走態勢に入っている.

(もちろん今回挙げた3つのポイントを持って十分に大勢を語れているかどうか,というのは各企業の技術評価担当の方がそれぞれ自己責任で検討する必要がある.)

MySQLばかり持ち上げているようにも見えるが,これが現在の私の正直な感想である.細かい比較もかなり行っているが,最も影響度の高い要素を抽出して考え,各RDBMSの現状を特徴付けて説明すると,このような結果となる.

私はSIerの社員でもあるし,本来特定のRDBMSを贔屓する必然性は無い.1人のエンジニアとしては,全ての主要プロダクトに,今回上げた技術についての対応を進め,どのプロダクトを選択しても安心して使える,というような状況になってくれることを望んでいる.