ストーリー
「新しいプロジェクトのデータベースはMongoDBでいきましょう!」
チームメンバーの提案に、高橋アーキテクトが落ち着いて問いかける。
「なぜMongoDBなんだ? 技術選定は『使いたいから』ではなく『要件に合っているから』で判断する。RDBとNoSQL、それぞれの強みと限界を正しく理解した上で選ぶんだ」
判断フレームワーク
Step 1: データの特性を分析する
| 質問 | RDB寄り | NoSQL寄り |
|---|---|---|
| データ構造は固定か? | 固定・変更少ない | 柔軟・頻繁に変わる |
| 関連(リレーション)は複雑か? | 複雑なJOINが必要 | シンプルな関連 |
| トランザクションの要件は? | ACID必須 | 結果整合性で十分 |
| データ量は? | 数百万~数億行 | 数十億行以上 |
| スケール要件は? | 垂直スケールで十分 | 水平スケール必須 |
Step 2: アクセスパターンを分析する
| 質問 | RDB寄り | NoSQL寄り |
|---|---|---|
| 読み書きの比率は? | 読み書き均等 | 読み重 or 書き重に偏る |
| クエリパターンは? | 多様・アドホック | 固定的・予測可能 |
| レイテンシ要件は? | 数十ms許容 | サブミリ秒が必要 |
| 同時接続数は? | 数百~数千 | 数万~数十万 |
比較表
| 特性 | RDB | NoSQL |
|---|---|---|
| スキーマ | 固定(schema-on-write) | 柔軟(schema-on-read) |
| 整合性 | 強い整合性(ACID) | 結果整合性(BASE) |
| スケーリング | 垂直(スケールアップ) | 水平(スケールアウト) |
| JOIN | ネイティブサポート | 限定的 or なし |
| トランザクション | 完全サポート | 限定的サポート |
| クエリ言語 | SQL(標準化) | 製品固有のAPI |
| 成熟度 | 50年以上の歴史 | 比較的新しい |
ユースケース別の推奨
RDBが適しているケース
1. 金融・決済システム
→ ACID トランザクションが必須
→ 複雑なリレーションと整合性制約
2. ERPシステム
→ 構造化された定型データ
→ 複雑なレポート・集計クエリ
3. ユーザー管理・認証
→ 一意性制約(email, username)
→ 外部キーによる参照整合性
// RDB向き: 送金処理(ACID必須)
async function transferFunds(
fromAccountId: number,
toAccountId: number,
amount: number
): Promise<void> {
await prisma.$transaction(async (tx) => {
// 送金元の残高を減らす
const from = await tx.account.update({
where: { id: fromAccountId },
data: { balance: { decrement: amount } },
});
if (from.balance < 0) {
throw new Error('Insufficient funds');
}
// 送金先の残高を増やす
await tx.account.update({
where: { id: toAccountId },
data: { balance: { increment: amount } },
});
});
}
NoSQLが適しているケース
1. SNSのタイムライン
→ 大量の書き込みと読み込み
→ 柔軟なコンテンツ構造(テキスト、画像、動画)
2. IoTデータ
→ 大量の時系列データの書き込み
→ 水平スケールが必須
3. リアルタイムゲーム
→ サブミリ秒のレスポンス要件
→ セッション状態の高速管理
4. コンテンツ管理(CMS)
→ 各記事が異なる構造を持つ
→ スキーマの柔軟性が必要
// NoSQL向き: CMSのコンテンツ管理(MongoDB)
// 記事の種類によって構造が異なる
const blogPost = {
_id: new ObjectId(),
type: 'blog',
title: 'MongoDBの使い方',
body: '...',
tags: ['mongodb', 'database'],
author: { name: '田中', avatar: '/img/tanaka.jpg' },
};
const photoGallery = {
_id: new ObjectId(),
type: 'gallery',
title: '春の写真集',
photos: [
{ url: '/img/1.jpg', caption: '桜', exif: { camera: 'Sony A7', iso: 400 } },
{ url: '/img/2.jpg', caption: '梅', exif: { camera: 'Canon R5', iso: 200 } },
],
};
CAP定理
分散システムでは、以下の3つのうち2つまでしか同時に満たせない。
Consistency(一貫性)
/\
/ \
/ \
/ CAP \
/________\
Availability Partition Tolerance
(可用性) (分断耐性)
| 組み合わせ | 特性 | 例 |
|---|---|---|
| CP | 一貫性 + 分断耐性 | HBase, MongoDB (デフォルト) |
| AP | 可用性 + 分断耐性 | Cassandra, DynamoDB |
| CA | 一貫性 + 可用性 | 単一ノードRDB(分散でない) |
よくある間違い
| 間違い | 正しい判断 |
|---|---|
| 「スケールするからNoSQL」 | RDBもRead Replicaやパーティショニングでスケールする |
| 「スキーマがないから楽」 | スキーマはアプリ層に移動するだけ。設計は必要 |
| 「NoSQLは速い」 | 適切な設計のRDBも十分速い。用途次第 |
| 「RDBは時代遅れ」 | 2024年でもRDBは最も信頼性の高いストア |
| 「MongoDBは何でも使える」 | 複雑なJOINが必要な場面ではRDBが適切 |
判断フローチャート
データに強い整合性が必要?
├── Yes → RDB(PostgreSQL, MySQL)
└── No
├── アクセスパターンは Key-Value 型?
│ ├── Yes → Redis / DynamoDB
│ └── No
│ ├── データ構造が柔軟?
│ │ ├── Yes → MongoDB
│ │ └── No
│ │ ├── 時系列データの大量書き込み?
│ │ │ ├── Yes → Cassandra / TimescaleDB
│ │ │ └── No
│ │ │ └── 関係性の深い探索?
│ │ │ ├── Yes → Neo4j
│ │ │ └── No → RDB
まとめ
| ポイント | 内容 |
|---|---|
| 判断基準 | データ特性とアクセスパターンで決める |
| RDBの強み | ACID、JOIN、SQL、成熟度 |
| NoSQLの強み | スケーラビリティ、柔軟性、特化性能 |
| CAP定理 | 分散システムの制約を理解する |
| 組み合わせ | ポリグロットパーシステンスで両方活用 |
理解度チェックリスト
- RDBとNoSQLの特性の違いを5つ以上挙げられる
- ユースケースに応じた適切なデータストアを選択できる
- CAP定理を説明できる
- 「NoSQLを選ぶべきではない」ケースを判断できる
次のステップ
次は演習:NoSQLで設計しよう。実際のシナリオに対して最適なNoSQLデータストアを選び、データモデルを設計する。
推定読了時間: 25分