具体的な記事や製品については論争になるのでなるべく触れませんが、2025年現在から近い将来にかけて分散RDBの利用が広まるかどうかについて、ポエムを書いてみました。
まとめ
- 1システムでの利用の規模はともかく、数に関しては共有メモリ構成のRDBが主流のまま変わらないのではないか
- NoSQL系も元々特定用途での特化、効率性を突き詰めており、想像以上にそもそものアーキテクチャ、ユースケースが異なるので、ジャンルとして残り続けるのではないか
- 分散RDBは強く求められるシステムでは利用されるだろうが、様々な要因によりメイン・ストリームにならないであろう
以下、筆者が思いつく理由を順番に見ていきます。
そもそも分散システムは処理効率が悪い
分散システムは、複数ノードに分散することより、1ノードでは達成できない高度な特性(可用性、耐久性、スケーラビリティ、セキュリティ、データアクセス etc...)を透過的に提供します。
しかしながら、そもそも分散システムはその特性上、単純な処理効率が悪いです。
ノード間のアクセスに時間がかかる
こちらのテキストにまとめられている通り、同一ホスト内でのメモリ上のデータアクセスに比べて、同一データセンター内でのラウンドトリップは桁違いに遅いことがわかります。
たとえば、メモリ上の1対1のジョインはBTreeインデックスで検索を行うことで、1msを大きく下回る時間で実行可能かもしれませんが、別のノードにデータを取得する必要となった時点で少なくとも数百マイクロ秒、複数ノードを順番にアクセスするとミリ秒のオーダーに達してもおかしくありません。
Latency Numbers Every Programmer Should Know
Latency Comparison Numbers (~2012)
...
Main memory reference 100 ns 20x L2 cache, 200x L1 cache
...
Read 4K randomly from SSD* 150,000 ns 150 us ~1GB/sec SSD
...
Round trip within same datacenter 500,000 ns 500 us
...
Send packet CA->Netherlands->CA 150,000,000 ns 150,000 us 150 ms
RDBで求められる処理は1対多、多対多、3つ以上のテーブルによるジョインなども含まれ、アクセスする行数、ノード数、ジョイン対象のテーブル数が増えれば増えるほど外部のノードへのアクセス数が増加します。
また、RDBではデータの整合性の維持のために外部キー、チェック句、トリガーなどの機能も提供しており、これらの機能も分散RDBではネットワークを介した他のノードへのアクセスが求められることから、「共有メモリ構成のRDBでは1msもかからずに完了するクエリが、分散RDBではxxx ms以上かかる」といったことが普通にありえます。
数ms~数十ms程度であれば、アプリケーションの性能要件からみて十分許容できるかもしれませんが、レイテンシーが増大するということは1セッションで単位時間あたりに処理可能なクエリのスループットの大幅な減少を意味しています。
例えば、共有メモリ構成のDBの1セッションでのクエリの処理時間が0.1ms、分散RDBで同じクエリの処理時間が1msとします。
単純化のためにクライアントとのネットワークのラウンドトリップや、負荷の増加に伴うレイテンシーの悪化を無視すると、前者は1000/0.1=10,000クエリ/秒を実行可能であるのに対して、後者は1000/1=1000クエリ/秒と1/10の数しかクエリを実行できないことがわかります。
これは同じスループットをさばくために10倍のクライアントを用意する必要があることを意味しています。
必要なクライアント数の増加は即コストの増大に繋がります。
現実には共有メモリ構成のDBでもクライアント側とのネットワークのラウンドトリップは発生することや、1ノードの過負荷による応答性の低下が発生すること、クライアント側のスレッド数のみを増加させる等の方法を取ることが可能であることから単純な比較は難しいものの、同じスループットを発揮させるためのコストは増加すると考えられます。
以上のことを踏まえると、各コンポーネントの分散化を行った分散RDBよりも、DBのコンポーネント間のネットワークのラウンド・トリップが一切発生しない、シングル・ホストで動作する共有メモリ構成のRDBのほうがコストあたりのスループット、処理効率が高いことがわかります。
CPUの処理時間の大半はネットワーク・スタックである
こちらの論文で検証されているとおり、現代のDBにおいて、CPUの処理時間の大部分はTCP/IPのネットワーク・スタックであり、トランザクション処理ではありません。
OLTP Through the Looking Glass 16 Years Later:
Communication is the New Bottleneck
上記の論文での検証されているのは特定の一インフラのみ構成であり、PostgreSQL, VoltDBのみを調査対象としているので、実際にはインフラストラクチャやDBMS、ワークロード毎の差は大きいと考えられます。
しかしながら、CPUの処理時間のおおよそ何割かがネットワーク・スタックに費やされているということは、トランザクション処理に費やすことが可能なCPU時間がその分減少してしまうことを意味しています。
すなわち、共有メモリ構成の従来DBと同じスループットを発揮するためにより多くのハードウェアを並べる必要があり、1ノードあたりの処理効率が低下することを意味しています。
効率的なデータ配置、実行計画の作成が極めて難しい
共有メモリ構成のRDBにおいても、効率的な実行計画の作成は難しい問題ですが、分散RDBでは「タプル、テーブルをどのように各ノードに配置するか」という問題が新たに発生することから、複雑さが増大しています。
こちらの書籍にて、パーティショニング(書籍中はFragmentationと呼ばれます)の複雑さについて言及がされています。
Principles of Distributed Database Systems (English Edition) 4th Edition
分散RDBでは分散KVSのように固定的に主キーで分散すればよいという単純なものではなく、複雑なジョイン処理を最適化するためには、クエリごとのジョイン・グラフを分析し最適なノードの分散を決定する、タプルのアクセス統計を取得しノード配置を決定する、ワークロードの変更に追従して再度最適化する等、複雑で高度な仕組みが要求されます。
手動でもジョインの最適化は実施可能かもしれませんが、システムの規模が大きくなり、何千、何万種類の複雑なクエリを手動で管理、最適化することは現実的ではないので、本格的にRDBと同じように利用するならば、前述の仕組みは必要になると考えられます。
仕組みの複雑化は高コスト化、動作の安定性の問題が発生し、手動でのチューニングは多くの工数が発生するので、これはこれで運用、維持管理の高コスト化につながります。
「そもそも分散システムは処理効率が悪い」のまとめ
以上のように、分散RDBはネットワークのラウンド・トリップが多く発生することからコストが高く、単純な費用対効果でみるとシングル・ノードの共有メモリ構成のRDBには敵わないことから、初めから何らかの要件により高度な分散RDBが望まれる場合を除いて「デフォルトでとりあえず分散RDBを選択しよう」とはならないのではないでしょうか。
DBに限らずITシステムはコスト効率、費用対効果をシビアに求められる分野であり、コストの高さ、性能効率の悪さを正当化できる必要があります。
もちろん、分散RDBで解決できる高度な要件、困りごとが存在する場合には選択肢になると考えられますが、システムの規模、ワークロードが大きかったり、大企業で地理分散が求められる等の要件が主で、中小企業や中小WebサービスのRDBを置き換える、デフォルトの選択肢になるなどといったことには、なかなかならないのではないでしょうか。
NoSQLやDWHは元々特定用途での特化、効率性を突き詰めており、想像以上にアーキテクチャ、想定しているユースケースが異なる
分散RDBの普及によりNoSQLの利用がなくなる、選択されなくなるといった意見もありますが、NoSQL系DBMSと分散RDBは似ているようで、そもそもアーキテクチャ、想定しているユースケースが大きく異なります。
NoSQLは特定用途での費用対効果が高い仕組みを採用していることから、部分的に分散RDBと重複しているかもしれまんが、大部分はそのまま利用、採用され続けるのではないでしょうか。
論争になりそうなので具体的なプロダクトの比較、深堀は避けますが、以下のような分散RDBとして求められる機能、特性は言い換えれば全てコストの増大、レイテンシーの悪化につながり、その機能実現のために多くの開発、維持保守のリソースが必要となることから、これらを妥協ないし、逆に特定要素を追求した特化型のNoSQLは費用対効果が高いプロダクトとして存続するのではないでしょうか。
- フルスペックのSQL言語を提供する
- 各ノードの統計情報を取得し、実行計画のインプットとする
- 実行されるクエリのジョイン・グラフに応じてテーブル、タプルの配置を動的に最適化する
- 複雑なクエリをパースし、実行計画を作成する
- クライアントとの複数のネットワークのラウンドトリップが発生する、インタラクティブなACIDトランザクションを提供する
- MVCCによるロックフリーの読み取り処理を提供する
- MVCCによるデータベースの一貫性のあるスナップショットを提供する
- 常に強い整合性を提供する
- 既存のRDBと同じwire protcol互換を提供する
- DDLにより同期的なスキーマ定義の更新を提供する
etc...
例えばインメモリDBや全文検索エンジン、分散KVSはすでに利用が広まっていますし、SQLを実行できるDBMSとしてDWHやBigdataの系統のクエリ実行エンジンはRDBとは別にOLAP用途にそれぞれ需要があります。
以下、簡単にそれぞれの特性を見ていきます。
DWH
DWHについてはクエリのレイテンシーをある程度諦める代わりに複雑なクエリ、大量データの効率的な検索に特化しており、そもそものデータ構造やオプティマイザーの最適化のポイントが大きく異なります。
OLTP用のDBでは低いレイテンシー(多くの場合、ミリ秒、もしくは以下)で応答し、小さなクエリを大量に並列度で実行することに特化しています。
一方でDWHではプロダクト次第であるものの、ノードの階層構造が深い構成でクエリを分散実行する、時間を掛けて実行計画の最適化を実施する、SIMD命令を駆使したvectorized scanの実施、データ構造としてcolumnar型で保存する等、OLTP用のDBとは大きく仕組みが異なります。
1クエリで多くのリソースを利用することから、セッション・レベルの並列度に関してもOLTP用DBと比べて一般的に低いです。
RDBとしての機能を持っているプロダクトもあればそうでないものもあり、RDBに近いものの、性能もそうですし可用性、耐久性等の特性も分散RDBとは異なると考えられます。
インメモリDB
インメモリDBはデータの耐久性や複雑なクエリ言語のサポートを排除する代わりに極めて低レイテンシーで読み込み、書き込みを実施可能であり、アプリケーションからの利用には注意が必要であるものの、書き込みよりも読み込みが多数発生し厳密な整合性が要求されない用途で広く利用されています。
データの読み込みの低レイテンシーを維持したまま、書き込みのレイテンシー、データ永続化のコスト等を許容するプロダクトも存在し、多様化、高機能化が行われています。
全文検索エンジン
全文検索エンジンについては、RDBにおけるMVCCやコミット直後にデータをすぐ参照可能になる、一貫性のある読み取り等の機能は提供されておらずRDBとは根本的に異なるものの、近しいドキュメントの検索からログの分析、異常検知、直近ではベクトル検索等の用途で広く利用されています。
分散KVS
分散KVSについては、RDBにおけるSQLの実行やMVCC、読み取り一貫性、インタラクティブなトランザクション処理などの多くの機能が提供されていませんが、代わりに主キーでの高速なアクセスに特化しており、安定した低レイテンシー、素早いスケールアウト、RDBで求められる機能、特性を排除したことによる低コスト等の特徴があります。
オープンソースとして提供されるものもあれば、DBaaSとして提供されるものもあり、Big Techはいずれも各社の要件に合致した分散KVSを内製化していることから、Webアプリケーションの多くのワークロードを効率的に実行可能であると考えられます。
プロダクトによるものの、分散ACIDトランザクションのサポート、Sparkとの統合、CDCのサポート、KVS以外のデータ・モデルのサポート、キャッシュ機能の統合、分析ワークロード実行のための別のデータストアへの自動レプリケーション等、多くの機能がサポートされ、独自の要件に基づき進化を続けています。
「NoSQLやDWHは元々特定用途での特化、効率性を突き詰めており、想像以上にアーキテクチャ、想定しているユースケースが異なる」のまとめ
見てきたように、分散RDBでは機能性はともかくとして、いずれのカテゴリのNoSQL、あるいはDWHが特化している用途に関して同じ特性、コスト効率で実現することは難しいと考えられます。
では分散RDBはどういった用途で使われるのか?
分散RDBは以下のような用途では利用されるのではないでしょうか。
- 性能の要件
- 共有メモリ構成のRDBの1ノードでは性能要件を満たさない
- 書き込みスループットの要求が高いので、非同期リード・レプリカによるスケールアウトでは要件を満たさない
- スループットの要件を満たすならば、クエリのレイテンシーの増加は許容される
- データの整合性、一貫性の要件
- 整合性の問題で、非同期リード・レプリカのよるスケールアウトでは要件を満たさない
- 遠隔地の複数のDCに分散しつつデータの整合性も維持したい
- 可用性の要件
- 共有メモリ構成のRDBのプライマリーをSPoFにしたくない
- 遠隔地の複数のDCに分散して可用性を向上させたい
- アプリケーションの互換性の要件
- 現実的にアプリケーションを用途特化のNoSQL向けに書き換えることが難しい
- コストの要件
- 分散RDBの利用、運用に伴うコストの増加は許容される
概ね、「レイテンシーの悪化が想定されても、スケーラビリティや可用性を向上させつつもRDBと同レベルの高度な要件を実現したい、コストを掛けることは許容される」といった用途になるのではないでしょうか。
Webアプリケーションで広く利用されるNoSQLや手動シャーディングはなるべく低コストにスケールアウトさせることに特化していることから、一見似ていそうで方向性が大きく異なるのではないかと考えられます。
クエリのレイテンシーが増加することから単純な性能向上には繋がらないことや、RDBにおける多くのワークロードでは読み込み処理が支配的であることから、共有メモリ構成のRDBの上位互換として採用することも難しいと考えられます。
非同期リード・レプリカでのスケールアウトでは実現できないデータの整合性の維持は魅力的ですが、共有メモリ構成のRDBでもTime-Based MVCCを実施できるはずなので、個人的には分散RDBの仕組みを一部取り入れてこの点だけピンポイントで改善したプロダクトが登場するのではないかと予想しています。
最後に
結局、DBはITシステムの1コンポーネントに過ぎず、「コスパが良いか、実績があるか、必要な機能を提供しているか、運用や開発のノウハウがあるのか、将来性があるか、サポート体制が整っているか etc...」などをシビアに見られる分野です。
分散システムは本質的なネットワークのラウンドトリップによる遅延等の物理法則は覆せないことから、数字を無視して、一部の界隈で期待されているように、既存のDBを置き換えてデファクト・スタンダード化することにはならないのではないでしょうか。
個人的な意見ですが、数字や現実を見ない分散RDBへの過度な期待はEV万能論、再エネ万能論などに通じるものがある気がしますね。