前回、と言ってもずいぶん前になるが
超並列RDBMSは成立するか – L.star的デザイン(1)
にてある程度の考察をしているRDBMSのデザイン。kumoFSどうだろうとか寄り道しつつ、自分なりの次のステージまで煮詰めることができたので、それについてメモとして書き留めたい。
まず目標として掲げるのは、
- 標準的なストレージしか持たないサーバ群を使う。
- 単純CRUDクエリのスケールアウト。読み書き両方
- JOIN構文のサポート。特に1TB程度の複数テーブルをINNER JOINして集計できる
- 1つのクエリ内部を複数サーバに分割させることによる性能向上。スケールアウトというわけではないが。
というところである。かなり無茶な要求と思うが、ここまでサポートできるとデザイン上で納得できれば悪くなかろう。現実に実装する場合には、随所で発生するボトルネックとの戦いになるだろうし。前回は「ストレージノード」と「クエリ実行ノード」の2種類に分けたが、今回はここをより深く切り分けて、実際どのように並列化可能か、というのを取り上げたい。
読み込みI/Oをレプリケーションで、書き込みはパーティショニングで分散するRAIO1+0構成のストレージノード
ストレージノードは、RDBMSの従来のボトルネックであったディスクI/Oを司るところだから大切にしたいところである。しかし、ここをどうやって構成するか、というのは最近もはや定番構成ができつつある。まず書き込みI/Oを分割するためにShardingする。後にこれをレプリケーションすることによって可用性と読み込みの分散の両方をはかるやりかたである。以下に構成例を図で示す。
これは詰まるところディスクで言うところのRAID1+0構成になる。逆の0+1(先に複製、あとでsharding)という構成とどっちがありかというのは難しいが、分割したものは全てそろっていないといけないこと、複製は全てそろっている必要はないことから、先に分割するのが順当に思われる。
実行プランの垂直・水平分割
次に実際にここからデータを読み込んだ後、結合とかソートとか集約演算をする、クエリ実行ノードの話に移る。RDBMSにおけるクエリ実行プランには、実は2種類の分割が可能である。一つは各クエリオペレータは、基本的に上流から来たデータを下流に流す構造なので、これは垂直分割可能である。例えばデータを読むノードと、それを加工するノードは別にすることが可能である。つまりクエリ実行ノードは、複数のクエリオペレータノードに分割可能である。
ただし理論上は分割可能だが、別ノードやプロセスに置くとプロセス間通信が発生する。これをできるだけ最小化する
また、ソートや集約については水平分割も可能である。例えばソートの場合マージソートにより分割可能である。マージソートは外部記憶を使うこともできるので分散の必要はないが、ネットワーク越しにすることでこの外部記憶用ディスクへのI/Oも負荷分散可能である。JOINに関しては、巨大なテーブル同士でまともな性能が出るのはマージジョイン以外あり得ず、そのため必要なのはソートなので、ここがあれば大丈夫である。
以下に具体的に2テーブルのJOINをするときのフロー例を示す。この例では各テーブルが5つにshardingされているとし、おのおの前処理として集約とソートしつつ、最後にJOINして合計21ノードで処理をしている。ここでは「ノード」としたが、物理的に別ノードである必要はない。
というわけで、ここでは4種類の並列可能性を抽出してみた。これにごくごく当たり前のものを加えると
- Shardingによる読み書きI/Oの分散
- レプリケーションによる読みI/Oの分散および可用性向上
- 実行プランの垂直分割
- クエリオペレータの並列実行
- 接続ごとの並列実行
これら全てを組み合わせたシステムが実は案外多くないことに注意する必要があるだろう。クエリベースのレプリケーションは上記のうち2と5だけしか使わない。Postgres-XCは1も備えるが、現状3を備えないためにノードをまたがったテーブルのJOINができない。世の多くのKVSは1,2,5についてはほぼ完璧である。ただ、3,4については無いに等しいか、SQLより簡素化したもの(例えばMapReduce)しか備えない。3,4に強いのは実はOLAP系のツールで、RDBMSより圧倒的に強い。
これらを加味すると、1-5を全て備えるために必要なのは、KVSのような1,2に強いストレージモデルにしつつ、なおかつその上にOLAP系ツールに近いSQLインターフェースを配置する必要がある。ただ、推測でしかないがSalesforceの内部、Azure向けSQL Server、そしてOracle exadataはこれに近いデザインになっているだろうというか、他に妥当なデザインが思い浮かばない。正直これ以上デザインを推し進めたとき、どれだけ彼らの特許に引っかかるかと思うと憂鬱になる。
まあここでのデザインはあくまで自分の訓練向けと思っているし、かなりのボリュームなのでたぶん全部を実装するのは一人では手に余る。まあそれでも時間を見つけてインターフェース起こしたりより詳細な実装に踏み込んだり、という作業はやっている。例えばクエリのフローの流れや、具体的なストレージノードの初期デザインも頭の中にはできているので、とにかくそういうのをメモ代わりにここに残しながら少しづつ完成に近づけていきたい。でないと、とても現状の最先端には追いつけない。
コメント