「NoSQL」という言葉は曖昧なバズワードであり、本質的に別物のデータベース群をひとくくりにしています。RDB経験者がNoSQLを学ぶときに最初に押さえるべきは、NoSQLを一括りにせず4つのデータモデルとして個別に捉えることです。本記事ではこの4分類と各モデルの特徴・代表プロダクト、そして「複雑度」と「関連度」という2つの軸でNoSQLを整理する考え方を扱います。
前提: RDB(リレーショナルデータベース)とは
NoSQLを語るには、対比対象であるRDB(リレーショナルデータベース)の特徴を先に押さえておく必要があります。
RDBは以下のような特徴を持ちます。
- データを表(テーブル)として格納する。各テーブルには事前に定義された列(スキーマ)があり、全行が同じ列構成を持つ
- テーブル間の関連を外部キーで表現し、JOINで複数テーブルを結合してクエリできる
- 操作はSQLという標準化されたクエリ言語で記述する
- ACIDトランザクションを提供し、複数テーブルにまたがる更新でも整合性を保てる(強整合性)。詳細は ACIDトランザクションの4特性 を参照
- パフォーマンスは主にスケールアップ(より高性能なサーバーへの置き換え)で上げる
代表的なプロダクトとして PostgreSQL、MySQL、Oracle Database、SQL Server などがあります。業務システムや基幹システムで長年使われており、現在もデータベースの第一選択肢として広く採用されています。
RDBは「型・関連・トランザクション」を強く支援する代わりに、データ量や流量が増えたときに水平方向のスケール(複数サーバーへの分散)が難しいという特性があります。NoSQLはこの「分散しにくさ」をデータモデル側から作り直したデータベース群、と理解するのが本質的です。
NoSQLは「RDB以外」ではない
NoSQLを「RDB以外のデータベース」と理解するのは大きな誤解です。NoSQLというラベルが指す範囲は広く、その中の各プロダクトは性質が大きく異なります。
たとえばRedis(キーバリュー)とNeo4j(グラフ)は同じ「NoSQL」というカテゴリに分類されますが、データモデル・クエリ・スケーラビリティ・ユースケースのいずれを取っても共通点はほとんどありません。「NoSQLを使う」という会話は、それだけではほとんど情報量がありません。
書籍『RDB技術者のためのNoSQLガイド』はこの問題に対し、NoSQLという単語を極力避け、KVS/ドキュメントDB/グラフDBという具体的な種別で語る立場を取っています。本記事もこのスタンスに倣います。
NoSQLの4つのデータモデル
NoSQLは大きく以下の4つのデータモデルに分類できます。
キーバリュー(KVS)
キーに対して1つの値を取るシンプルなデータ構造です。RDBで例えるなら「カラムが2つだけのテーブル」に近い構造で、キーと値のセットでデータを格納します。代表プロダクトは Redis、Memcached、Riak などです。
KVSの中でも特殊な位置づけのRedisは、値として複雑なデータ構造(リスト・セット・ハッシュ・ソート済みセット等)を格納できる「データ構造サーバ」として機能します。単純なキーバリューに留まらず、リアルタイムランキング・タイムライン・Pub/Sub などの用途にも使われます。
ワイドカラム
キーに対して複数の列を持ち、行ごとに持つ列の組み合わせが違ってもよいモデルです。KVSの一種として分類されることもあります。Cassandra や HBase のような代表的なワイドカラムDBは、後述の LSM-tree というストレージ実装を採用しているため大量書き込みに強い特徴がありますが、これはデータモデル由来ではなく実装由来である点に注意が必要です(後述)。
RDBとの違いを並べると以下のようになります。
RDB(全行が同じ列を持つ)
| id | name | email | age |
|----|--------|-----------------|------|
| 1 | Alice | alice@ex.com | 30 |
| 2 | Bob | NULL | NULL | ← 値はNULLだが列自体は存在する
| 3 | Carol | carol@ex.com | 25 |
ワイドカラム(行ごとに列構成が違う)
行1: { id: 1, name: "Alice", email: "alice@ex.com", age: 30 }
行2: { id: 2, name: "Bob", phone: "090-..." } ← 別の列セットを持つ
行3: { id: 3, name: "Carol", email: "carol@ex.com", address: "Tokyo" }
RDBでは列はテーブル定義時に確定し、値がなくてもNULLとして列自体は存在します。ワイドカラムでは新しい列を事前のスキーマ変更なしに追加でき、ある行に存在しない列はそもそも保持されません。「センサー機種ごとに送ってくる項目が違う」「ユーザーごとにキャプチャするイベント種別が違う」といった疎なデータを扱うのに向いており、RDBで同じことをやると「使われない列だらけのNULLだらけテーブル」になりがちです。
代表プロダクトは Cassandra、HBase、Amazon DynamoDB などです。
「NoSQL = スキーマレス」とは限らない点には注意が必要です。Cassandraはバージョン0.8以降スキーマ定義が必須となっており、CQL(Cassandra Query Language)で事前にテーブル構造を定義してから使います。ただしテーブル定義後も列の追加は柔軟に行えます。
ドキュメント
キーに対してJSON(または類似の階層構造)を値として格納するモデルです。半構造データ(フィールドがアイテムごとに違う、ネストがある)を扱うのに向いており、Web/モバイルアプリのバックエンドで広く使われています。代表プロダクトは MongoDB、Couchbase、CouchDB、Microsoft Cosmos DB などです。
スキーマは事前定義不要なものが多いですが、必要に応じてスキーマバリデーションを強制できるプロダクトも増えています。「スキーマレスだが必要に応じてスキーマを強制できる」柔軟性が現代のドキュメントDBの特徴です。
グラフ
ノード(点)・関係性(辺)・属性(プロパティ)の3要素で「物事の繋がり」を表現するモデルです。RDBで何度も自己結合を繰り返さないと書けないようなクエリ(「友達の友達の友達」「ある駅から別の駅への最短経路」など)を、グラフ探索として効率的に処理できます。代表プロダクトは Neo4j、OrientDB などです。
「データ間の繋がり自体が価値を持つ」業務(詐欺検知、レコメンド、経路探索、人材検索など)で真価を発揮します。逆に集計中心のレポーティングやログ解析のような用途には向きません。
「複雑度」と「関連度」は別の軸
ここがNoSQLを理解するうえで重要なポイントです。データモデルを語るとき、複雑度と関連度は別の軸として整理する必要があります。
複雑度とは(1件のデータがどれだけ豊かな構造を持てるか)
複雑度は「1つのデータ単位がどれだけ表現力のある構造を持てるか」を指します。たとえばキーバリューはキー1つに対して値1つしか持てませんが、ドキュメントは階層構造を持つJSONを格納でき、グラフは関係性そのものにも属性を付けられます。
| データモデル | 1件のデータ | 表現力 |
|---|---|---|
| キーバリュー | キー : 値 | 値1つだけ |
| ワイドカラム | キー : 可変列 | 行ごとに違う列構成を持てる |
| ドキュメント | キー : JSON | ネスト・配列を含む階層構造 |
| リレーショナル | テーブル+外部キー | 複数テーブルが関連を持てる |
| グラフ | ノード+関係性+属性 | 関係性そのものにも属性を付けられる |
複雑度の順序で並べると以下のようになります。
キーバリュー < ワイドカラム < ドキュメント < リレーショナル < グラフ
関連度とは(データ同士の繋がりの強さ)
関連度は「データ同士の繋がりがどれだけ強く・直接的に表現されているか」を指します。
- KVS・ワイドカラム・ドキュメントは、基本的に各データがキーで独立しており、データ間の関連は弱い構造です。あるドキュメントから別のドキュメントを参照する場合も、アプリケーション側でキーを使って引き直す形になります
- リレーショナルは外部キーで関連を表現し、JOINで他テーブルのデータを取得できます
- グラフは関係性そのものがデータの主役で、ノード間の関係を辿る操作がクエリの中心になります
関連度の順序で並べると、複雑度とは違う順序になります。
キーバリュー = ワイドカラム = ドキュメント < リレーショナル < グラフ
複雑度と関連度は混同されやすい
「ドキュメントDBはJSONをネストできるから関連度が高い」と誤解されることがありますが、これは複雑度の話であって関連度ではありません。あるドキュメントの内側にネストされたサブオブジェクトはあくまで「1件のデータの内部構造」であり、別のドキュメントとの関連ではありません。
たとえばMongoDBで users コレクションの各ドキュメントが orders 配列を内部に持っていても、それは「ユーザーの内部データ」であって「ユーザーと注文の関連」ではありません。別の orders コレクションを作ってユーザーIDで参照する設計にしたとしても、その関連はMongoDBではなくアプリケーション側が解釈する必要があります。これがリレーショナルやグラフとの本質的な違いです。
関連度はスケーラビリティと反比例する
ここがNoSQLの設計思想を理解する核心です。関連度が高いデータは分散配置しにくく、結果としてスケーラビリティが下がります。
| データモデル | 関連度 | 分散の容易さ |
|---|---|---|
| KVS / ワイドカラム / ドキュメント | 低 | 容易(キーでシャーディング) |
| リレーショナル | 中 | 中(外部キーをまたぐとトランザクションが複雑) |
| グラフ | 高 | 困難(関係を辿るたびにノード跨ぎが発生) |
グラフDBはRDBよりスケーラビリティが低い
ここが直感に反する事実です。「NoSQLだからスケーラブル」というのは誤解で、グラフDBはNoSQLに分類されるが、RDBよりもスケーラビリティが低いケースが多くあります。
たとえばNeo4jは標準ではシャーディング不可で、データもクエリも分散できません。単一ノードのメモリに収まる量がデータの上限になります。スケールアウトの代替手段としてHAクラスタによる読み取り負荷分散や、エンタープライズ版のキャッシュシャーディングがありますが、書き込みのスケールアウトはRDBよりさらに難しい構造です。
グラフDBを選ぶときは「スケーラビリティを得るため」ではなく「関係性の表現力と探索性能を得るため」と理解する必要があります。
NoSQL 4分類のサマリー
| 分類 | データ単位 | データモデル由来の強み | 代表プロダクト | 典型ユースケース |
|---|---|---|---|---|
| キーバリュー | キー : 値 | キーで分散しやすい・低レイテンシ参照 | Redis, Memcached, Riak | キャッシュ・セッション・カウンタ・ランキング |
| ワイドカラム | キー : 可変列 | 行ごとに違う列構成・疎なデータの効率格納 | Cassandra, HBase, DynamoDB | IoT時系列・メッセージング・ユーザ行動ログ |
| ドキュメント | キー : JSON | 半構造データ・スキーマ柔軟性 | MongoDB, Couchbase, Cosmos DB | Webアプリバックエンド・カタログ・ログ |
| グラフ | ノード+関係性 | 関係性の探索 | Neo4j, OrientDB | 詐欺検知・レコメンド・経路探索 |
代表プロダクトの書き込み性能は、データモデルではなくストレージ実装(LSM-tree など)に由来します。次節でこの違いを補足します。
補足: ワイドカラムが書き込みに強いのはLSM-tree由来
「ワイドカラム = 大量書き込みに強い」という言説をよく見かけますが、これはデータモデル由来の性質ではなく、ストレージ実装由来です。
Cassandra や HBase が大量書き込みに強い理由は、LSM-tree(Log-Structured Merge Tree) というストレージ実装にあります。書き込みパスは以下のようになります。
- コミットログ(WAL)に追記。シーケンシャル書き込み
- メモリ上の memtable に書く。ここで書き込み完了を返せる
- memtable がしきい値を超えたらまとめて SSTable としてディスクに書き出す。シーケンシャル書き込み
- 後で複数の SSTable をコンパクションで1つにまとめる
ポイントは「書き込み時にランダム I/O が発生しない」「in-place update しない(既存データを書き換えず追記のみ)」「ロック競合が少ない」ことです。RDB の B-tree が採用する「ページを直接書き換える」方式は更新時にランダム I/O とページロックが発生するため、書き込みスループットで LSM-tree に劣ります。
LSM-tree は実装上の選択であり、ドキュメントDBの一部(MongoDB の WiredTiger など)も類似の構造を採用できます。「ワイドカラムだから書き込みに強い」のではなく「Cassandra/HBase が LSM-tree を採用しているから書き込みに強い」が正しい理解です。LSM-tree と B-tree の書き込み・読み取り・コンパクションの構造比較は『ストレージエンジンの2大潮流: B-tree と LSM tree の構造比較』を参照してください。
なお、ノード数に対してどれだけ綺麗に性能が伸びるか(線形スケーラビリティ)はストレージ実装ではなくクラスタアーキテクチャ(マスターレス/マスタースレーブなど)の話で、別記事 応答速度×スケール方式によるデータベース分類 で扱います。
4分類で語ることの実務的メリット
技術選定の議論で「NoSQLを検討します」と言っても、何を比較すればいいか定まりません。一方「ドキュメントDBを検討します」「KVSをキャッシュ用途で導入します」と言えば、評価軸が明確になります。
- データモデルの適合性: 業務データはキー・値で済むのか、JSON的なのか、グラフ的なのか
- クエリ要件: キー検索だけで済むか、集計や結合が要るか、グラフ探索が要るか
- スケーラビリティ要件: 単一ノードで足りるか、水平分散が必要か
- 整合性要件: 強整合性が必須か、結果整合性で許容できるか
これらは4分類によって満たし方が大きく異なるため、最初に「どの分類か」を決めてから個別プロダクトの比較に進むのが効率的です。
分類を決めたあとの個別プロダクトの整理は『主要NoSQLプロダクトリファレンス: Redis・Cassandra・DynamoDB・MongoDB・Neo4j を中心に』で扱っています。
「キャッシュならRedis」「時系列ならCassandra」のように、ユースケース起点で候補プロダクトを逆引きする整理は『ユースケース別NoSQL選定ガイド: 「こういうときはどのNoSQL?」を逆引きする』で扱っています。
まとめ
- NoSQLは曖昧なバズワードであり、KVS・ワイドカラム・ドキュメント・グラフの4つのデータモデルとして捉える
- 「NoSQL = スキーマレス」「NoSQL = RDB以外」「NoSQL = スケーラブル」はいずれも単純化しすぎた誤解
- データモデルには複雑度の順序(KV < ワイドカラム < ドキュメント < リレーショナル < グラフ)と関連度の順序(KV = ワイドカラム = ドキュメント < リレーショナル < グラフ)があり、両者は別の軸
- 関連度が高いほど分散しにくく、スケーラビリティは下がる
- グラフDBはNoSQLだがRDBよりスケーラビリティが低い点に注意(シャーディング不可な実装が多い)
- 技術選定の議論では「NoSQL」ではなく「KVS/ワイドカラム/ドキュメント/グラフ」と4分類で語るのが第一歩