NoSQL

リレーショナルモデル以外のデータベースの総称で、スケーラビリティと柔軟性を重視する

データベースアーキテクチャ
NoSQL」の技術書を見る →

NoSQL とは

NoSQL (Not Only SQL) は、リレーショナルモデル (テーブル + SQL) 以外のデータベースの総称で、水平スケーラビリティ、柔軟なスキーマ、高スループットを重視する。DynamoDB、MongoDB、Redis、Cassandra が代表例。名前は「SQL を使わない」ではなく「SQL だけではない (Not Only SQL)」の意味で使われ、SQL に似た問い合わせ言語を備える製品も含む。

水平に伸びる理由は単純で、データをキーで分割して別々のノードに置くからだ。その代わり、複数ノードにまたがる結合や集計、全データを通した一意制約といった「行を横断して見る機能」を手放している。NoSQL の選定は、この手放した分をアプリケーション側の設計で埋められるかの判断になる。

NoSQL の種類

分類の軸は保存形式そのものではなく「どのキーで引けるか」だ。キーバリューは主キーの完全一致だけを引き受け、キーのハッシュ値で置き場所のノードが決まるため台数を増やすほど素直に伸びる。ドキュメントは値の中身 (JSON の各フィールド) にも索引を張れるので、主キーを知らない検索ができる。カラムファミリーは 1 行を列単位に分けて保存し、同じパーティション内をソートキー順に並べて置くため、時系列の範囲取得が連続読み取りで済む。グラフは関係そのものをデータとして持ち、隣のノードへの参照を辿るので、多段の辿り (友人の友人) がテーブル結合の繰り返しにならない。

種類データモデルAWS サービス用途
キーバリューキー → 値DynamoDBセッション、キャッシュ
ドキュメントJSON ドキュメントDocumentDBCMS、カタログ
カラムファミリー列指向Keyspaces (Cassandra)時系列、ログ
グラフノード + エッジNeptuneSNS、不正検知

RDB vs NoSQL

違いはスキーマの有無だけではない。分散させるために何を諦めたか、という軸で並べると対応が見える。

観点RDB (RDS)NoSQL (DynamoDB)
スキーマ固定 (事前定義)柔軟 (スキーマレス)
スケーリング垂直 (スケールアップ)水平 (スケールアウト)
JOIN複数のテーブルをクエリ側で結合できる結合は行えず、必要な項目を 1 つの項目にまとめて持たせる
トランザクションACID限定的 (DynamoDB Transactions)
一貫性強い整合性結果整合性 (強い整合性もオプション)
用途複雑なリレーション高スループット、大規模データ

DynamoDB の特徴

スキーマレスは「何でも入る」ではない。テーブル定義で宣言するのは主キー (とインデックスのキー) だけで、それ以外の属性はアイテムごとに有無が変わってよい、という意味だ。

// スキーマレス: アイテムごとに異なる属性を持てる
await db.put({ TableName: 'items', Item: { id: '1', name: 'Alice', age: 30 } });
await db.put({ TableName: 'items', Item: { id: '2', name: 'Bob', tags: ['admin'] } });
// age がないアイテム、tags があるアイテムが共存

この自由さの裏返しが 2 つある。1 つはインデックスの疎性で、DynamoDB はインデックスのキー属性を持つアイテムだけを索引に書くため、その属性が無いアイテムはインデックスに現れない。処理中の注文だけに目印の属性を付けて索く用途では利点になるが、一覧の取りこぼしの原因にもなる。もう 1 つは属性名の綴り違いがエラーにならないことで、別名の属性が 1 つ増えるだけなので、書き込み側で属性名を定数にまとめておかないと気づけない。

選択基準

複雑なリレーションや JOIN が必要なら RDB (RDS, Aurora)、高スループット・低レイテンシなら DynamoDB、柔軟なスキーマなら DynamoDB や DocumentDB、グラフ構造 (SNS、推薦) なら Neptune、キャッシュやセッションなら ElastiCache (Redis)、全文検索なら OpenSearch が適している。

CAP 定理

CAP 定理は Consistency (全ノードが同じデータを返す)、Availability (全リクエストに応答する)、Partition Tolerance (ネットワーク分断に耐える) の頭文字で、「3 つのうち 2 つしか選べない」と紹介されることが多い。この言い方は正確ではない。選択が発生するのはネットワーク分断が起きている間だけで、分断は起こるものなので P は前提であり、そのとき一貫性と可用性のどちらを諦めるかの二択になる、というのが定理の内容である。分断していない平常時は両方成り立つ。

DynamoDB は分断時に可用性を残す側 (AP) で、読み取りの既定は結果整合性である。

DynamoDB の基本操作

読み取りの既定は結果整合性で、直前の書き込みを必ず反映させたい場所だけ ConsistentRead: true を指定する。強い整合性の読み取りは読み込み容量の消費が結果整合性の 2 倍になり (2026 年 8 月時点)、グローバルセカンダリインデックスとストリームからの読み取りには指定できない。整合性が必要な読み取り経路をインデックス頼みで組むと、後からこの制約に突き当たる。

// 主キー完全一致の取得 (既定 = 結果整合性)
const item = await db.get({ TableName: 'items', Key: { id: '1' } });

// 直前の書き込みを必ず反映させたい読み取りだけ強い整合性にする
const fresh = await db.get({
  TableName: 'items',
  Key: { id: '1' },
  ConsistentRead: true,
});

選ぶ順序を間違えないことが実務では効く。先にアクセスパターン (どのキーで何を、どの頻度で引くか) を書き出し、それが列挙できてから NoSQL を検討する。列挙できないうちは RDB で始めて、負荷が集まった経路だけを後から切り出す方が、逆順よりやり直しが小さい。

この記事は役に立ちましたか?

関連用語

関連する記事