サイトアイコンmaita tomoya dev io

データベース基礎

データベース

データベース基礎

データベースとは何か

データベースとは、データを効率的に保存・管理・検索するための仕組みのこと。

身近な例で考えてみよう。図書館を想像してほしい。

図書館 = データベース

+---------------------------------------------------+
|                   図書館(データベース)              |
|                                                     |
|  書棚(テーブル)                                    |
|  +-----------------------------------------------+ |
|  | 小説棚   | 技術書棚  | 雑誌棚   | 漫画棚     | |
|  | (novels) | (tech)   | (mags)   | (comics)   | |
|  +-----------------------------------------------+ |
|                                                     |
|  カード目録(インデックス)                          |
|  +-----------------------------------------------+ |
|  | タイトル順 | 著者順  | 出版年順 | ジャンル順  | |
|  +-----------------------------------------------+ |
|                                                     |
|  図書カード(レコード/行)                           |
|  +-----------------------------------------------+ |
|  | ID: 001                                        | |
|  | タイトル: データベース入門                       | |
|  | 著者: 山田太郎                                  | |
|  | ISBN: 978-4-xxxx-xxxx-x                        | |
|  | 棚番号: B-3-12                                  | |
|  +-----------------------------------------------+ |
+---------------------------------------------------+

この対応関係を整理すると以下のようになる。

図書館の要素データベースの要素説明
図書館全体データベースデータの集まり全体
書棚(ジャンル別)テーブル同じ種類のデータをまとめた入れ物
図書カード1枚レコード(行)1件分のデータ
カードの記入項目カラム(列)データの各項目(タイトル、著者など)
カード目録インデックス素早くデータを見つけるための索引
図書館のルール制約データの正しさを保つためのルール(必須項目など)

カード目録がなければ、本を探すたびに全ての書棚を端から順に見ていく必要がある。データベースのインデックスも同じで、検索を高速にするための仕組みだ。

なぜデータベースが必要か

「ファイル(CSVやJSON)にデータを保存すればいいのでは?」と思うかもしれない。小規模なデータならそれでも問題ないが、アプリケーションが成長すると以下の問題が発生する。

ファイル管理 vs データベースの比較

課題ファイル管理データベース
同時アクセス複数人が同時に編集するとデータが壊れるロック機構で安全に同時アクセスできる
データの整合性矛盾したデータが入り放題制約(NOT NULL、UNIQUEなど)で防止できる
検索速度ファイルが大きくなると遅いインデックスで高速検索が可能
障害時の復旧クラッシュするとデータが失われるトランザクションログで復旧可能
データの関連付けファイル間の関連を自分で管理する必要がある外部キーやJOINで簡単に関連付けできる
バックアップ・復元手動でコピーするしかないバックアップ・リストア機能が組み込まれている

具体例: ユーザーデータの管理

CSVファイルでユーザーデータを管理する場合を考えてみよう。

users.csv:
id,name,email
1,田中太郎,taro@example.com
2,佐藤花子,hanako@example.com

orders.csv:
id,user_id,item,price
1,1,本,1500
2,1,ペン,200

この方式だと以下の問題が起きる。

  • プログラムAがusers.csvを読み込んでいる最中に、プログラムBが書き込むとデータが壊れる
  • user_id=999の注文データを入れてもエラーにならない(存在しないユーザー)
  • 「田中太郎が買った商品の合計金額」を求めるには、2つのファイルを読み込んで自力で紐付ける必要がある
  • users.csvが100万行になると検索が非常に遅い

データベースなら、これらの問題を全て解決できる。

ACID特性

ACID特性とは、データベースのトランザクション(一連の操作のまとまり)が満たすべき4つの性質のこと。信頼性のあるデータベースの基盤となる概念だ。

銀行振込の例で理解する

太郎の口座から花子の口座に1万円を送金する処理で考えてみよう。

操作1: 太郎の残高を1万円減らす(10万円 → 9万円)
操作2: 花子の残高を1万円増やす(5万円 → 6万円)

各特性の詳細

特性英語説明銀行振込での例
原子性(Atomicity)Atomicity全て成功するか、全て失敗するか。中途半端な状態にならない操作1だけ成功して操作2が失敗 → 両方ロールバック。太郎のお金は減らない
一貫性(Consistency)Consistencyトランザクション前後でデータの整合性が保たれる送金前の合計15万円 = 送金後の合計15万円。お金が増えたり消えたりしない
独立性(Isolation)Isolation同時に実行されるトランザクション同士が干渉しない太郎が花子に送金中に、次郎も花子に送金しても、金額がおかしくならない
永続性(Durability)DurabilityCOMMITされたデータは、障害が発生しても失われない送金完了後にサーバーが停電しても、花子の口座には1万円が入ったまま

ACIDの図解

トランザクション(振込処理)
+------------------------------------------------------------------+
|                                                                    |
|  BEGIN                                                             |
|    |                                                               |
|    v                                                               |
|  操作1: 太郎の残高 -10,000円                                       |
|    |                                                               |
|    v                                                               |
|  操作2: 花子の残高 +10,000円                                       |
|    |                                                               |
|    +--- 成功 ---> COMMIT  ---> 変更が確定(永続性)                |
|    |                                                               |
|    +--- 失敗 ---> ROLLBACK ---> 全ての変更を取り消し(原子性)     |
|                                                                    |
+------------------------------------------------------------------+

独立性: 他のトランザクションからは、この処理の途中経過が見えない
一貫性: 処理前後で合計金額は変わらない

データベースの種類一覧と比較

データベースにはさまざまな種類があり、用途に応じて使い分ける。

リレーショナルデータベース(RDB)

データを**テーブル(表)として管理し、テーブル同士をリレーション(関連)**で結びつける。最も広く使われているタイプ。

RDB特徴ライセンス主な採用企業
PostgreSQL高機能、拡張性が高い、JSON対応PostgreSQLライセンスApple、Instagram、Spotify、Reddit
MySQL高速読み取り、Web開発で人気GPL / 商用Facebook、Twitter、YouTube
Oracleエンタープライズ向け、高価商用ライセンス銀行、保険、大企業
SQL ServerMicrosoft製、Windows環境に強い商用ライセンスMicrosoft系企業
SQLiteファイルベース、組み込み用途パブリックドメインモバイルアプリ、ブラウザ

ドキュメントデータベース

データをJSON形式のドキュメントとして保存する。スキーマが柔軟で、アジャイル開発に向いている。

ドキュメントDB特徴主な用途
MongoDB最も人気のあるNoSQLデータベースWebアプリ、CMS、ログ収集
FirestoreGoogle製、リアルタイム同期モバイルアプリ、チャット
CouchDBオフライン同期に強いモバイルアプリ
RDBのデータ構造:
users テーブル
+----+--------+------------------+
| id | name   | email            |
+----+--------+------------------+
| 1  | 太郎   | taro@example.com |
+----+--------+------------------+

ドキュメントDBのデータ構造:
{
  "_id": "user001",
  "name": "太郎",
  "email": "taro@example.com",
  "address": {
    "city": "東京",
    "zip": "100-0001"
  },
  "hobbies": ["読書", "プログラミング"]
}

キーバリュー型データベース

**キー(名前)とバリュー(値)**のペアでデータを保存する。極めて高速で、キャッシュやセッション管理に使われる。

キーバリューDB特徴主な用途
Redisインメモリ、超高速キャッシュ、セッション、ランキング
DynamoDBAWS製、フルマネージド、スケーラブルサーバーレスアプリ、IoT
MemcachedシンプルなキャッシュWebアプリのキャッシュ
キーバリューのイメージ:
+------------------------+-------------------+
| キー                   | バリュー          |
+------------------------+-------------------+
| "user:1:name"          | "太郎"            |
| "session:abc123"       | "{...セッション}" |
| "cache:top_products"   | "[{...}, {...}]"  |
+------------------------+-------------------+

グラフデータベース

データを**ノード(点)エッジ(辺)**で表現する。関係性の分析に特化。

グラフDB特徴主な用途
Neo4j最も人気のあるグラフDBSNS、レコメンド、不正検知
ArangoDBマルチモデル対応複合的なデータモデル
グラフDBのイメージ:
    (太郎) ---[友人]--> (花子)
       |                  |
    [購入]             [購入]
       |                  |
       v                  v
    (商品A)            (商品B)
       |
    [類似]
       |
       v
    (商品C)

→「太郎の友人が買った商品」「商品Aに似ている商品」を高速に検索できる

時系列データベース

時間順に並んだデータの保存と分析に特化。IoTセンサーデータやメトリクス収集に最適。

時系列DB特徴主な用途
InfluxDB時系列データ専用サーバー監視、IoT
TimescaleDBPostgreSQL拡張メトリクス、金融データ
Prometheus監視に特化アプリケーション監視

全文検索エンジン

テキストの全文検索に特化したデータベース。形態素解析やあいまい検索が可能。

全文検索エンジン特徴主な用途
Elasticsearch最も人気、分散検索エンジンログ分析、サイト内検索
OpenSearchElasticsearchのフォークAWS環境でのログ分析
Meilisearch軽量、高速、簡単に使える小中規模のサイト内検索

CAP定理

分散データベースを設計する際の重要な理論。3つの性質のうち、同時に2つまでしか満たせないという定理。

3つの性質

性質英語説明
一貫性(C)Consistency全てのノードが同じデータを返す
可用性(A)Availability全てのリクエストに応答を返す(エラーでも何か返す)
分断耐性(P)Partition Toleranceネットワーク障害が起きてもシステムが動作し続ける

CAP定理の図解

                  一貫性 (C)
                    /\
                   /  \
                  /    \
                 / CA   \
                /  領域  \
               /----------\
              /            \
             / CP    AP     \
            /   領域   領域  \
           /                  \
          +--------------------+
    可用性 (A)           分断耐性 (P)

CA: PostgreSQL, MySQL(単一ノード)
   → ネットワーク分断が起きないことを前提とする
CP: MongoDB, Redis Cluster, HBase
   → 一貫性を優先し、分断時はリクエストを拒否する可能性がある
AP: DynamoDB, Cassandra, CouchDB
   → 可用性を優先し、一時的にデータが古い可能性がある

実務での考え方

インターネットを介した分散システムでは、ネットワーク分断は必ず起こる。そのため、実質的にはCPかAPのどちらかを選ぶことになる。

ユースケース選択理由
銀行の残高管理CPデータが間違っていたら大問題
SNSのタイムラインAP多少古いデータが見えても大きな問題はない
ECサイトの在庫管理CP在庫がないのに注文できたら問題
ニュースフィードAP数秒の遅延は許容される

RDB vs NoSQL

使い分けフローチャート

データの構造は決まっているか?
├── はい → データ間に複雑な関連があるか?
│           ├── はい → RDB(PostgreSQL, MySQL)
│           └── いいえ → データ量は非常に大きいか?
│                        ├── はい → NoSQL(DynamoDB, Cassandra)
│                        └── いいえ → RDB(シンプルで十分)
│
└── いいえ → どんな検索が必要か?
             ├── キーで1件取得 → キーバリュー(Redis, DynamoDB)
             ├── 全文検索 → Elasticsearch
             ├── 関係性の探索 → グラフDB(Neo4j)
             ├── 時系列の集計 → 時系列DB(InfluxDB)
             └── 柔軟な構造 → ドキュメントDB(MongoDB, Firestore)

比較表

比較項目RDB(PostgreSQL等)ドキュメントDB(MongoDB等)キーバリュー(Redis等)
データ構造テーブル(行と列)JSON形式のドキュメントキーとバリューのペア
スキーマ固定スキーマ(事前定義が必要)スキーマレス(柔軟)なし
関連データJOINで結合埋め込みまたは参照非対応
トランザクション強力(ACID完全対応)限定的(ドキュメント単位)限定的
スケーリング垂直(スケールアップ)が基本水平(スケールアウト)が容易水平スケーリング対応
検索の柔軟性SQL(非常に柔軟)クエリ言語(やや制限あり)キー指定のみ
学習コストSQLの習得が必要JSONの理解があれば始められる非常に低い
代表的なユースケースECサイト、金融、業務システムCMS、モバイルアプリ、IoTキャッシュ、セッション管理

スキーマとスキーマレスの違い

スキーマあり(RDB)

スキーマとは、データの構造を事前に定義したもの。テーブルのカラム名、データ型、制約などを決めてからデータを投入する。

-- スキーマの定義(テーブル構造を先に決める)
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    email VARCHAR(255) UNIQUE NOT NULL,
    age INTEGER CHECK (age >= 0)
);

-- スキーマに合わないデータは拒否される
INSERT INTO users (id, name, email, age) VALUES (1, '太郎', 'taro@example.com', 25);  -- 成功
INSERT INTO users (id, name, email, age) VALUES (2, NULL, 'test@example.com', 25);     -- 失敗(nameがNULL)
INSERT INTO users (id, name, email, age) VALUES (3, '花子', 'taro@example.com', 28);   -- 失敗(emailが重複)

メリット: データの品質が保証される。型の不一致や必須項目の欠落を防げる。 デメリット: スキーマの変更(ALTER TABLE)が必要で、大規模テーブルでは時間がかかる場合がある。

スキーマレス(NoSQL)

データの構造を事前に定義しない。各ドキュメントが異なる構造を持てる。

// ドキュメント1
{
  "name": "太郎",
  "email": "taro@example.com",
  "age": 25
}

// ドキュメント2(フィールドが異なる)
{
  "name": "花子",
  "email": "hanako@example.com",
  "phone": "090-xxxx-xxxx",
  "address": {
    "city": "大阪",
    "zip": "530-0001"
  }
}

メリット: 柔軟にデータ構造を変更できる。開発初期の試行錯誤がしやすい。 デメリット: データの品質はアプリケーション側で保証する必要がある。

どちらを選ぶか

状況推奨
データ構造が明確で、変更が少ないスキーマあり(RDB)
データ構造が頻繁に変わるスキーマレス
データの整合性が重要スキーマあり(RDB)
開発スピードを優先したいスキーマレス
複数のアプリケーションから同じDBを使うスキーマあり(RDB)

正規化 vs 非正規化

正規化とは

正規化とは、データの重複を排除してテーブルを効率的に設計する手法。データの一貫性を保ちやすくなる。

正規化前(非正規形):
+--------+--------+----------+--------+------+------+
| 注文ID | 顧客名 | 顧客住所 | 商品名 | 単価 | 数量 |
+--------+--------+----------+--------+------+------+
| 1      | 太郎   | 東京都   | 本A    | 1500 | 2    |
| 1      | 太郎   | 東京都   | ペンB  | 200  | 3    |
| 2      | 花子   | 大阪府   | 本A    | 1500 | 1    |
+--------+--------+----------+--------+------+------+

問題: 「太郎」「東京都」が重複。太郎が引っ越したら全行を更新する必要がある。

正規化後:
顧客テーブル           商品テーブル           注文テーブル
+----+------+------+   +----+------+------+   +----+------+
| id | 名前 | 住所 |   | id | 名前 | 単価 |   | id | 顧客 |
+----+------+------+   +----+------+------+   +----+------+
| 1  | 太郎 | 東京 |   | 1  | 本A  | 1500 |   | 1  | 1    |
| 2  | 花子 | 大阪 |   | 2  | ペンB| 200  |   | 2  | 2    |
+----+------+------+   +----+------+------+   +----+------+

注文明細テーブル
+------+------+------+
| 注文 | 商品 | 数量 |
+------+------+------+
| 1    | 1    | 2    |
| 1    | 2    | 3    |
| 2    | 1    | 1    |
+------+------+------+

非正規化とは

意図的にデータの重複を許容して、読み取り性能を向上させる手法。

非正規化の例(注文履歴テーブル):
+--------+--------+--------+------+------+
| 注文ID | 顧客名 | 商品名 | 単価 | 数量 |
+--------+--------+--------+------+------+
| 1      | 太郎   | 本A    | 1500 | 2    |
| 1      | 太郎   | ペンB  | 200  | 3    |
+--------+--------+--------+------+------+

→ JOINなしで注文内容を一発で取得できる(読み取りが速い)
→ ただし「太郎」が重複しているので、更新が面倒

いつどちらを選ぶか

状況推奨理由
通常の業務アプリケーション正規化データの一貫性が重要
読み取りが極端に多い(レポート、分析)非正規化JOINのコストを避けて読み取り速度を上げる
データの更新が多い正規化更新箇所を最小化できる
リアルタイム分析、ダッシュボード非正規化事前に集計したデータを保持
小中規模のアプリケーション正規化まず正規化から始めるのが基本
大規模アクセスのWebサービス両方併用正規化したテーブル + 非正規化したキャッシュ層

実務での基本方針: まず正規化で設計し、パフォーマンスが問題になった箇所だけ非正規化を検討する。

トランザクション分離レベル

複数のトランザクションが同時に実行されるとき、他のトランザクションの変更がどこまで見えるかを決める設定。

発生しうる問題

問題英語説明
ダーティリードDirty Read他のトランザクションのCOMMIT前のデータが見える
ノンリピータブルリードNon-repeatable Read同じクエリを2回実行すると、別の結果が返る(他が更新した)
ファントムリードPhantom Read同じ条件で検索すると、行数が変わる(他が挿入/削除した)

分離レベルの比較表

分離レベルダーティリードノンリピータブルリードファントムリードパフォーマンス
READ UNCOMMITTED発生する発生する発生する最速
READ COMMITTED防止発生する発生する速い
REPEATABLE READ防止防止発生するやや遅い
SERIALIZABLE防止防止防止最も遅い

各レベルの解説

READ UNCOMMITTED(未コミット読み取り)

他のトランザクションがCOMMITしていないデータも読める。最も緩い分離レベル。

トランザクションA                トランザクションB
BEGIN;
UPDATE users SET age=30          BEGIN;
  WHERE id=1;
                                 SELECT age FROM users WHERE id=1;
                                 → 30が見える(まだCOMMITしていない!)
ROLLBACK;
                                 → 30を使って処理を進めてしまう
                                    (実際にはROLLBACKされて元の値に戻った)

READ COMMITTED(コミット済み読み取り)

PostgreSQLのデフォルト。COMMITされたデータのみ読める。

トランザクションA                トランザクションB
BEGIN;                           BEGIN;
UPDATE users SET age=30          SELECT age FROM users WHERE id=1;
  WHERE id=1;                    → 25(COMMIT前なので古い値)
COMMIT;
                                 SELECT age FROM users WHERE id=1;
                                 → 30(COMMITされたので新しい値)
                                 ※同じクエリなのに結果が変わる!

REPEATABLE READ(反復読み取り)

トランザクション開始時のスナップショットを使う。同じクエリは常に同じ結果を返す。

トランザクションA                トランザクションB
                                 BEGIN;
                                 SELECT age FROM users WHERE id=1;
                                 → 25
BEGIN;
UPDATE users SET age=30
  WHERE id=1;
COMMIT;
                                 SELECT age FROM users WHERE id=1;
                                 → 25(スナップショットなので変わらない)
                                 COMMIT;

SERIALIZABLE(直列化可能)

最も厳格。トランザクションを1つずつ順番に実行したのと同じ結果を保証する。

実務での選び方

ユースケース推奨レベル理由
一般的なWebアプリケーションREAD COMMITTEDバランスが良い(PostgreSQLのデフォルト)
レポート生成REPEATABLE READ一貫したデータでレポートを作成
金融取引SERIALIZABLE絶対にデータの不整合を許さない
ログ書き込みREAD COMMITTED多少の不整合は許容される

インデックスの基本

インデックスとは

インデックスとは、データベースの検索を高速化するための仕組み。本の巻末にある「索引」と同じ考え方だ。

本の索引の例:
+------------------+--------+
| キーワード       | ページ |
+------------------+--------+
| ACID             | 45     |
| インデックス     | 78     |
| カーソル         | 112    |
| トランザクション | 45, 93 |
+------------------+--------+

→ 「トランザクション」を調べたいとき
   索引なし: 1ページ目から順に読む(遅い)
   索引あり: 索引を見て45ページと93ページに直行(速い)

B-treeインデックス

最も一般的なインデックスの種類。ほとんどのRDBでデフォルトで使われる。

B-tree(バランスツリー)の構造:

                    [50]
                   /    \
              [20,35]    [70,85]
             /  |  \    /  |  \
          [10] [25] [40] [60] [75] [90]
           |    |    |    |    |    |
          行   行   行   行   行   行

検索例: id=60 を探す場合
1. ルート [50] → 60 > 50 なので右へ
2. [70,85] → 60 < 70 なので左の子へ
3. [60] → 見つかった!

→ 100万行あっても、20回程度の比較で見つかる(log2(1000000) ≒ 20)

なぜ検索が速くなるか

検索方法100万行での比較回数時間計算量
全件スキャン(索引なし)最大100万回O(n)
B-treeインデックス約20回O(log n)

注意点: インデックスは検索を速くするが、データの挿入・更新・削除のたびにインデックスも更新する必要があるため、書き込みは遅くなる。

インデックスを作るべき場面

場面理由
WHERE句で頻繁に使うカラム検索条件のカラムにインデックスがあると速い
JOINの結合条件に使うカラム外部キーにはインデックスを作るのが基本
ORDER BYで使うカラムソートが高速化される
UNIQUEが必要なカラムUNIQUEインデックスで一意性を保証

インデックスを作らない方がよい場面

場面理由
テーブルが小さい(数百行以下)全件スキャンでも十分速い
INSERT/UPDATEが非常に多いカラムインデックスの更新コストが高くなる
カーディナリティが低いカラムtrue/falseなど値の種類が少ないとインデックスの効果が薄い
ほとんど検索に使わないカラム使わないインデックスは無駄なストレージ消費

データベース選定の判断基準

新しいプロジェクトでデータベースを選ぶ際のチェックリスト。

チェックリスト

チェック項目考慮事項
データの構造は明確か明確 → RDB、不明確 → ドキュメントDB
トランザクションは必要か必要 → RDB(ACID準拠)
読み取りと書き込みの比率は読み取り重視 → キャッシュ層を検討
スケーリング要件は水平スケーリング → NoSQL、垂直 → RDB
チームの技術スタックSQLの経験が豊富 → RDB、Node.jsメイン → MongoDB/Firestore
予算とコストOSS(PostgreSQL, MySQL)→ 無料、クラウドDB → 従量課金
運用・保守のしやすさマネージドサービス(RDS, Cloud SQL等)→ 運用負荷が低い
データの関連性複雑な関連 → RDB、シンプル → NoSQL
レイテンシ要件超低レイテンシ → Redis、通常 → RDB
データ量の見込みTB以上 → 分散DB(DynamoDB, Cassandra等)を検討

よくある構成パターン

パターン1: 一般的なWebアプリケーション
+-----------------+     +--------+
| アプリケーション | --> | PostgreSQL |
+-----------------+     +--------+

パターン2: キャッシュ層あり
+-----------------+     +-------+     +------------+
| アプリケーション | --> | Redis | --> | PostgreSQL |
+-----------------+     +-------+     +------------+
                     (キャッシュ)      (メインDB)

パターン3: 検索機能あり
+-----------------+     +------------+     +---------------+
| アプリケーション | --> | PostgreSQL | --> | Elasticsearch |
+-----------------+     +------------+     +---------------+
                       (メインDB)        (全文検索)

パターン4: マイクロサービス
+-----------+     +-------+
| サービスA | --> | PostgreSQL |
+-----------+     +-------+
+-----------+     +---------+
| サービスB | --> | MongoDB |
+-----------+     +---------+
+-----------+     +-------+
| サービスC | --> | Redis |
+-----------+     +-------+

主要データベース比較表

以下は、現在よく使われている主要なデータベースの比較表。

項目PostgreSQLMySQLMongoDBDynamoDBRedisSupabaseFirebase Firestore
種類RDBRDBドキュメントDBキーバリュー/ドキュメントキーバリューRDB(PostgreSQL)ドキュメントDB
ライセンスPostgreSQLライセンスGPL / 商用SSPLプロプライエタリBSDApache 2.0プロプライエタリ
スケーリング方式垂直 + 論理レプリケーション垂直 + レプリケーション水平シャーディング自動水平スケーリングクラスタリングSupabaseが管理自動水平スケーリング
トランザクションACID完全対応ACID(InnoDB)マルチドキュメント対応限定的限定的ACID完全対応限定的
JSON対応JSONB(高速)JSON型ネイティブネイティブJSON対応JSONB(高速)ネイティブ
全文検索内蔵(tsvector)FULLTEXT INDEXAtlas SearchなしRediSearch内蔵(PostgreSQL)なし
学習曲線やや高い普通低いやや高い低い低い(GUI充実)低い(SDK充実)
料金無料(OSS)無料(OSS)無料枠あり / 従量課金従量課金無料(OSS)無料枠あり / 従量課金無料枠あり / 従量課金
ホスティングセルフ / RDS / Cloud SQLセルフ / RDS / PlanetScaleAtlas / セルフAWSのみセルフ / ElastiCacheSupabase CloudFirebaseのみ
採用企業Apple, Instagram, SpotifyFacebook, YouTube, TwitterAdobe, ForbesAmazon, NetflixTwitter, GitHub多数のスタートアップGoogle系企業
強み機能の豊富さ、拡張性読み取り性能、エコシステム柔軟性、スケーラビリティ完全マネージド、スケーラビリティ超高速、データ構造が豊富開発体験、認証・ストレージ統合リアルタイム同期、SDK
弱み水平スケーリングの難しさ機能がPostgreSQLより少ないトランザクションの制限柔軟性の低さ永続化の制約PostgreSQLの制約を継承複雑なクエリが苦手

選定の目安

ユースケース推奨DB
一般的なWebアプリPostgreSQL / Supabase
モバイルアプリ(リアルタイム同期)Firebase Firestore
大規模ECサイトPostgreSQL + Redis
サーバーレスアプリDynamoDB / Firestore
キャッシュ / セッション管理Redis
CMS / ブログPostgreSQL / MongoDB
ログ分析Elasticsearch
プロトタイプ / MVPSupabase / Firebase

まとめ

データベースの基礎知識を振り返ろう。

概念ポイント
データベースとはデータを効率的に保存・管理・検索する仕組み
ACID特性原子性、一貫性、独立性、永続性でデータの信頼性を保証
CAP定理分散システムではC, A, Pのうち2つしか同時に満たせない
RDB vs NoSQL構造化データ + 関連 → RDB、柔軟性 + スケーラビリティ → NoSQL
正規化データの重複を排除して整合性を保つ(基本はこちら)
非正規化読み取り性能のために意図的に重複を許容する
トランザクション分離同時アクセス時のデータの見え方を制御するレベル設定
インデックスB-treeなどの構造で検索を高速化する(ただし書き込みは遅くなる)

データベースの選定に「正解」はない。プロジェクトの要件、チームのスキル、将来の成長を考慮して、最適なものを選ぶことが重要だ。迷ったらPostgreSQLから始めるのがよい。RDBの機能が充実しており、JSONBでドキュメントDBのような使い方もでき、無料で利用できる。

参考リンク