応答速度×スケール方式によるデータベース分類: RDBがスケールアウトしない理由とNoSQLの3つの妥協

「RDB」「NoSQL」と一言で語ると違いを掴んだつもりになりがちですが、実際にはRDBの中にもOLTP用とDWH用の別系譜があり、NoSQLの中にもオンライン処理向きのものとそうでないものがあります。本記事では応答速度(ターンアラウンドタイム vs スループット)とスケール方式(スケールアップ vs スケールアウト)の2軸でデータベースを4つの区分に分類し、各カテゴリ(RDB(OLTP)/KVS・ドキュメントDB/RDB(DWH)/Hadoop)がそこに位置する構造的理由を整理します。

応答速度とスケール方式の2軸で分類する

書籍『RDB技術者のためのNoSQLガイド』が提示する分類軸は、以下の2つです。

  • 軸1: 重視する性能 — ターンアラウンドタイム(1リクエストの応答速度)重視か、スループット(単位時間あたりの処理量)重視か
  • 軸2: 性能拡張モデル — スケールアップ(より高性能なサーバへの置き換え)か、スケールアウト(複数サーバへの分散)か

この2軸を掛け合わせると、データベースのカテゴリは以下の4セルに綺麗にマッピングされます。本記事の主題はRDB対NoSQLですが、両者の境界をはっきりさせるために対象外のカテゴリ(DWH用RDB・Hadoop)も配置しています。なおKVSは内部に「キーバリュー型」と「ワイドカラム型」の2種を持つため、右上のセル内ではNoSQLのサブタイプを分けて記載しています。

スケールアップ スケールアウト
ターンアラウンドタイム重視
(オンライン)
RDB(OLTP)
システム種別: RDB
PostgreSQL, MySQL, Oracle Database, SQL Server
KVS / ドキュメントDB
システム種別: NoSQL
  • KVS — キーバリュー型: Redis, Memcached, Riak
  • KVS — ワイドカラム型: Cassandra, HBase, DynamoDB
  • ドキュメントDB: MongoDB, Couchbase, CouchDB, Cosmos DB
スループット重視
(バッチ・分析)
RDB(DWH)
システム種別: RDB
Teradata, Netezza, Vertica, Greenplum, Oracle Exadata
Hadoop
システム種別: DB以外(分散バッチ処理基盤)
HDFS(ストレージ層)+ MapReduce / Spark(計算層)+ Hive(SQLレイヤ。任意)

本記事のRDB対NoSQLの対比は、左上(RDB OLTP)と右上(NoSQL)の比較が中心です。左下(RDB DWH)はRDBの別系譜として、右下(Hadoop)はNoSQLとよく混同される隣接領域として、参照のために置いています。それぞれのセルの特徴を見ていきます。

左上: RDB(OLTP)

OLTP(Online Transaction Processing、オンライントランザクション処理)は、ユーザの操作に応じてデータを即座に追加・更新・削除する処理形態を指します。たとえばECサイトで「注文を確定する」「在庫を1件減らす」「ユーザ情報を更新する」といった、人間が画面を待っているリクエストです。1リクエストの応答が遅いとユーザ体験が直接損なわれるため、ターンアラウンドタイムが最優先されます。対義語は後述するDWH(Data Warehouse、データウェアハウス)で、こちらは集計・分析向けにスループットを優先します。

業務システム・基幹システムで使われる伝統的なRDBはこのOLTP用途に最適化されており、1リクエストあたり数ミリ秒〜数十ミリ秒で応答することを最優先し、強整合性のトランザクションを提供します。スケールはCPU・メモリ・ディスクといったハードウェアを増強するスケールアップで対応するのが基本で、ノードを跨いだ書き込み分散は得意ではありません。

代表プロダクト: PostgreSQL, MySQL, Oracle Database, SQL Server

右上: KVS / ドキュメントDB(オンライン用NoSQL)

ターンアラウンドタイムを保ちつつ、スケールアウトで処理量を伸ばすために生まれたカテゴリです。RDBが提供していた強整合性や複雑なクエリを諦める代わりに、ノード追加で線形に性能を伸ばせる構造を持ちます(後述)。

このカテゴリは大きくKVS(キーバリューストア)とドキュメントDB(DocDB とも呼ばれる)の2種に分かれ、さらにKVSは内部に「キーバリュー型」と「ワイドカラム型」の2種を持つ階層構造になっています。

  • KVS(キーバリューストア)はキーに対して値を持つモデル
    • キーバリュー型は値が単一の値(Redis, Memcached, Riak)
    • ワイドカラム型は値が複数列で、行ごとに列の組み合わせが違ってもよい(Cassandra, HBase, DynamoDB)
  • ドキュメントDB(DocDB)はキーにJSON(または類似の階層構造)を持つモデル(MongoDB, Couchbase, CouchDB, Cosmos DB)

サブカテゴリそれぞれの違いと使い分けは NoSQLの4分類を整理する で扱っています。

右上の内部分化: 書き込みの線形スケーラビリティはクラスタアーキテクチャで分かれる

NoSQLは「スケールアウト可能」ということで右上に置かれていますが、その内部にも書き込み量が線形に伸びるかどうかでさらに分化します。決め手はデータモデルではなくクラスタアーキテクチャで、大きく以下の2タイプに分かれます。

  • マスタースレーブ型はマスター(プライマリ)が書き込みを受け、スレーブ(セカンダリ)に伝播する方式。読み込みはスレーブに分散できるが、書き込みはマスター1台が天井になる。マスター故障時はスレーブの昇格(フェイルオーバ)が必要で、その間は書き込みが止まる
  • マスターレス型は全ノードが等価で、書き込みも読み込みもどのノードでも受けられる方式。ノード追加でハッシュ空間を再分配し、データと処理の両方を分散させる。単一障害点がなく、ゴシッププロトコルでノード間の状態を伝播させる
観点マスタースレーブ型マスターレス型
書き込みを受けるノードマスター1台全ノード
書き込みのスケーラビリティ制約あり(マスターが天井)線形に近い
単一障害点あり(マスター)なし
フェイルオーバ必要(昇格処理)不要(リングからの離脱)
整合性のデフォルト強整合性に近い結果整合性
代表プロダクトRedis, MongoDB, RDBレプリケーションCassandra, Riak, DynamoDB

Cassandraがマルチデータセンタのレプリケーションを標準で組み込み、ノード数に対して書き込みスループットがほぼ線形に伸びるのは、このマスターレス型のリングアーキテクチャを採っているためです。

ただし「マスターレスだから常に優れている」わけではありません。マスターレス型は結果整合性(書き込み直後にレプリカ間で値がズレる時間窓があるが、最終的には全レプリカが同じ値に収束する整合性モデル。詳細は後述)が前提のため、「書いた直後に必ず読める」ことを保証したい用途には向きません。書き込みのスケーラビリティを取るか、整合性のシンプルさを取るかのトレードオフです。

マスタースレーブ型 = シングルリーダー方式、マスターレス型 = リーダーレス方式に対応します。両方式の仕組み・フェイルオーバー・競合解決の詳細は『レプリケーション戦略: シングルリーダー・マルチリーダー・リーダーレスの使い分け』を参照してください。

左下: RDB(DWH)

DWH(Data Warehouse、データウェアハウス)は、業務システム等から集めた大量のデータを蓄積し、集計・分析するために使うデータベースを指します。たとえば「過去1年の売上を商品カテゴリ別に集計する」「ユーザの行動ログから月次のリテンション率を計算する」「経営ダッシュボード向けのKPIを夜間バッチで再計算する」といった用途です。OLTPと違って人間が画面で待っているわけではないため、1クエリあたり数秒〜数分かかっても問題ありません。代わりに、テラバイト・ペタバイト級のデータを舐めるスループットが要求されます。

DWH用のRDBはこの用途に最適化されており、列指向ストレージや並列クエリ実行といった技術でスループットを稼ぎます。SQLが使えてACIDも維持されますが、用途は完全にバッチ・分析寄りで、業務システムのトランザクション処理には使いません。

代表プロダクト: Teradata, Netezza, Vertica, Greenplum, Oracle Exadata

右下: Hadoop

バッチ分析用のスケールアウト基盤です。「ストレージ層」と「計算層」が分離した構造になっており、巨大データをまず分散ファイルシステム HDFS(Hadoop Distributed File System)に書き込み、MapReduce または Spark といった計算エンジンが HDFS のデータを並列に読み込んで処理し、結果を再び HDFS に書き戻す、という流れで動きます。1ジョブの実行時間は数分〜数時間と長いですが、ペタバイト級のデータを並列処理できるのが強みです。

オプションで Hive という SQL レイヤを挟むこともできます。Hive は単独で動くものではなく、HiveQL(SQL風クエリ)を内部で MapReduce / Spark / Tez のジョブに変換し、HDFS のデータを処理させる「SQLからジョブへの翻訳役」です。SQLが書ける/書きたい人向けの上乗せレイヤと理解すれば十分です。

代表プロダクト: HDFS(ストレージ層)+ MapReduce / Spark(計算層)+ Hive(SQLレイヤ。任意)

グラフDBはどこに位置するか

グラフDBはこの分類の外側、RDB(OLTP)よりさらにスケールアウトしにくい位置に置かれます。データ間の「関係性」を辿るクエリが主役のため、関係を辿るたびにノードを跨いだ通信が発生し、分散と相性が悪い構造です。代表的なNeo4jは標準ではシャーディングできず、単一ノードのメモリに収まる範囲が事実上の上限になります。

「NoSQLだからスケールする」という単純化が誤解を生む典型例で、詳細は NoSQLの4分類を整理する で扱っています。

なぜRDB(OLTP)はスケールアウトに弱く、スケールアップに頼ることになるのか

RDB(OLTP)が左上のセル(スケールアップ)に分類されるのは、スケールアウト(複数ノードへの分散)と相性が悪い構造的理由があるためです。その根本原因は、ACIDのIsolation(独立性)を保つために必要なコストにあります。

1ノード内なら安いが、ノードを跨ぐと急に重くなる

  • 1ノード内のトランザクションは、WAL(Write-Ahead Logging)を書いてfsyncすれば終わるため比較的安価
  • ところが、複数ノードに跨ったトランザクションには2フェーズコミット(2PC)が必要で、台数が増えるほど応答が遅くなる

2フェーズコミットは「Prepare(全ノードに準備指示)→ Commit(全ノードに確定指示)」の2往復を全参加ノードと取る仕組みで、参加ノードが1台でも遅いとクラスタ全体が待たされます。詳細は ACIDトランザクションの4特性 で扱っています。

つまり「データ整合性を維持しようとするとトランザクションが必要、でもトランザクションをノード跨ぎでやると一気に重くなる」というジレンマが、RDBの水平分散の天井を作っているわけです。

スケールアップに頼る理由

このジレンマを回避する一つの方法が、1ノードで全部終わらせる=スケールアップです。CPUコア数・メモリ容量・ディスクI/O性能を上げれば、1台で処理できる量を増やせます。ただし、ハードウェアの性能向上には物理的な限界があり、コストも非線形に上昇します。

業務システムのように「データ量も流量も予測でき、強整合性が必須」という条件下では、このスケールアップ路線で十分長く戦えます。逆に「秒間万単位のリクエスト」「ペタバイト級のデータ」を相手にすると、この路線は早晩破綻します。

NoSQL(KVS / ドキュメントDB)がスケールを獲得した3つの工夫

KVS / ドキュメントDB はRDBの天井を超えるために、3つの妥協でスケールアウト可能な構造を作っています。

1. 分散トランザクションを提供しない

複数ノードに跨ったトランザクション(と、そのために必要な2フェーズコミット)をそもそも提供しません。トランザクションを「単一ノード内」「単一行内」に限定することで、コストの跳ね上がりを根本から避けています。

たとえばCassandraは複数行に跨るトランザクションをサポートせず、HBaseはトランザクション境界が「1行」に限定されています。

2. 分散しやすいデータ構造とクエリだけを提供する

JOIN・外部キー・複雑な集計といった「複数のデータを跨いで関連付ける」操作を提供しません。提供するのはキー検索を中心とした、ノードを跨がないクエリだけです。

これは制約のように見えますが、そもそもキー単位で独立したデータならば、ハッシュでノードに振り分けるだけで自然にスケールアウトできるという設計思想の裏返しです。データモデルとしてのキーバリュー・ワイドカラム・ドキュメントは、すべて「キーで独立しやすい」性質を共有しています。

3. 強整合性を犠牲にして、レプリカに対して読み書きする

書き込みを全レプリカに同期的に伝播させる代わりに、いったんは一部のレプリカだけに書いて応答を返し、残りは非同期で同期するモデルを採ります。これにより書き込みのレイテンシが下がり、ノードを増やせばスループットも線形に伸びます。

代償として、書いた直後に別のレプリカから読むと「まだ反映されていない古い値」が返ってくることがあります。これが結果整合性(Eventual Consistency)で、ACIDに対してBASE(Basically Available, Soft-state, Eventual Consistency)と呼ばれる弱い保証として整理されます。

これら3つの妥協はセットで効くもので、「分散トランザクションがないからこそ、分散しやすいクエリで済み、結果整合性で許容できる」という構造になっています。

CAP定理という別の分類軸

応答速度×スケール方式とは別に、データベースを CAP定理(Consistency/Availability/Partition tolerance のうち2つしか同時に満たせないという定理)で分類する切り口もあります。本記事の分類とは独立した整理軸です。CAP定理そのものの詳細は CAP定理(CA/CP/AP)とPACELC定理(PA/EL・PA/EC・PC/EC)による分散データベース分類 で扱っています。

領域からはみ出して進化している現状

ここまで4つの区分で整理してきましたが、現実の各データベースは生まれた区分から染み出して進化しています。

  • 応答が速いHadoopとして Impala、Presto、Hive on Tez が登場し、Hadoop上でターンアラウンドタイムを縮める方向に進化
  • 集計できるNoSQLとして MongoDB Aggregation、Couchbase、Cassandra が登場し、NoSQLにバッチ的な集計を持ち込む方向に進化
  • SQLが使えるNoSQLとして Cassandra CQL、Couchbase N1QL、DocumentDB SQL が登場し、学習コストの壁を下げる方向に進化
  • JSONを格納するRDBとして MySQL、PostgreSQL、SQL Server、DB2 が登場し、RDBが半構造データに対応する方向に進化
  • スケールアウトするRDBとして NewSQL(CockroachDB、TiDB、Spannerなど)が登場(本書出版時点では未収録)

ただし著者は「アーキテクチャの根幹は変えられないので、枝葉の機能は中途半端になる」と釘を刺しています。たとえばPostgreSQLのJSONサポートはMongoDB並みのドキュメント操作性を完全には提供しませんし、Cassandra CQLはRDBのSQLと比較するとJOINや集約がほぼ使えません。

技術選定の場面では「できる/できない」だけでなく「どこまでやれるか」「アーキテクチャの根幹に合っているか」を見極める必要があります。

NoSQL側のプロダクト個別の特性は『主要NoSQLプロダクトリファレンス: Redis・Cassandra・DynamoDB・MongoDB・Neo4j を中心に』で整理しています。ユースケースから候補プロダクトを逆引きする整理は『ユースケース別NoSQL選定ガイド: 「こういうときはどのNoSQL?」を逆引きする』で扱っています。

まとめ

  • データベースは応答速度(ターンアラウンドタイム vs スループット)とスケール方式(スケールアップ vs スケールアウト)の2軸で4つの区分に分類できる
  • ターンアラウンドタイム重視・スケールアップにRDB(OLTP)が位置する構造的理由は、ノード跨ぎでの2フェーズコミットがスケールアウトの天井になっていること
  • ターンアラウンドタイム重視・スケールアウトのKVS / ドキュメントDBは、「分散トランザクションを捨てる」「分散しやすいクエリだけ提供する」「結果整合性で妥協する」の3点セットでスケールアウトを獲得した
  • KVS / ドキュメントDBの中でも、書き込みの線形スケーラビリティはクラスタアーキテクチャ(マスタースレーブ vs マスターレス)でさらに分かれる
  • スループット重視・スケールアップにRDB(DWH)、スループット重視・スケールアウトにHadoopが位置し、いずれもバッチ分析向けでオンライン処理用途とは目的が違う
  • グラフDBはNoSQLだがスケールアウトに弱く、この分類の外側に位置する

参考書

タグ: RDB , NoSQL , データベース基礎