第9章 システム設計の流れ — 概念・論理・物理の 3 段階
この章で学ぶこと
- システム開発の流れの中でデータベース設計がどこに位置するかを説明できる
- 概念設計 / 論理設計 / 物理設計の 3 段階を区別し、それぞれの成果物を答えられる
- 設計プロセスが反復的に行われることを理解する
第 8 章 マスター vs トランザクション までを理解していること。本章から第 2 部「設計編」に入ります。
システム開発全体の流れ
データベース設計は、システム開発全体の中の一部です。全体像の中でどこに位置するかを把握しておきましょう。
データベース設計は 設計フェーズ に含まれます。要件定義で集めた「何を実現するか」を、具体的な「データの構造」に落とし込む工程です。
Jr が陥りやすい罠は「とりあえずテーブルを作って書き始める」ことです。プロトタイプならそれでも構いませんが、本番システムの設計を最初から CREATE TABLE で書き始めると、要件の見落とし・関係性の漏れ・正規化の崩れが後で発覚し、第 3 章で学んだ「後から直しにくい問題」が積み重なります。
データベース設計は 3 段階で進める
データベース設計は、抽象から具体へと 3 段階で進めるのが標準的なやり方です。
各段階の役割を一言で言うなら:
| 段階 | やること | 出てくるもの |
|---|---|---|
| 概念設計 | 業務の登場人物 (エンティティ) と関係を洗い出す | 概念 ER 図 (どの DBMS でも通用する抽象レベル) |
| 論理設計 | エンティティを RDB の表に落とし込み、正規化する | 論理 ER 図・テーブル一覧・カラム一覧 |
| 物理設計 | 実際の DBMS で動くテーブル定義に具体化 | CREATE TABLE 文・インデックス定義 |
概念設計 — 現実世界をモデル化する
概念設計は、業務を分析して「データとしてどんなモノが登場するか」「それらの関係は何か」を洗い出す段階です。RDB / NoSQL のような実装の話はまだ出てきません。
業務 → エンティティへの変換
概念 ER 図の例
エンティティ (entity): 業務に登場する「モノ」(社員 / 顧客 / 商品 / 注文 など)。やがてテーブルになる候補。
カーディナリティ (cardinality): 関係の多重度。「1 対 1」「1 対 多」「多 対 多」のいずれか。詳しくは第 12 章 E-R 図で扱います。
論理設計 — リレーショナル理論に基づいて詳細化
論理設計は、概念モデルを「RDB の表」として整理する段階です。正規化 (詳しくは第 11 章) や、主キー / 外部キーの設定 (第 10 章) がこの段階の中心作業です。
論理設計の成果物例
論理設計の段階では、データ型はまだ「文字列 / 数値 / 日付」程度の抽象レベルで構いません。
顧客 (顧客ID, 顧客名, 電話番号, メールアドレス, 住所)
商品 (商品ID, 商品名, カテゴリID, 標準価格)
注文 (注文ID, 顧客ID, 注文日時, 配送先住所, 合計金額)
注文明細 (注文ID, 商品ID, 数量, 単価, 小計)
このような「テーブル名 (属性 1, 属性 2, ...)」の表記は リレーション とも呼ばれます。主キーは下線で表すこともあります (顧客ID など)。
物理設計 — 実際の DBMS で動かせる形に
物理設計は、論理モデルを実際の DBMS で動かせるレベルまで具体化する段階です。次の判断をここで行います。
物理設計の成果物例
CREATE TABLE customers (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
phone VARCHAR(20),
email VARCHAR(255) UNIQUE NOT NULL,
address TEXT,
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_customers_email ON customers(email);
CREATE INDEX idx_customers_created_at ON customers(created_at);
データ型 (VARCHAR(100) / NUMERIC(12, 2) / TIMESTAMPTZ など)・インデックス・パーティションといった「実装の詳細」が、ここで初めて具体化されます。
3 段階に分ける利点
なぜ 3 段階に分けるのでしょうか。一気に CREATE TABLE まで書いてしまえば早いように見えますが、段階を分けることには明確な利点があります。
| 利点 | 説明 |
|---|---|
| 業務とコードの間に「翻訳」段階を置ける | 業務の人と概念モデルで議論し、エンジニアが論理→物理に翻訳 |
| 抽象度ごとに別の人が責任を持てる | 概念は業務分析者・物理は DBA、のような分業 |
| 部分的な変更がしやすい | DBMS を MySQL → PostgreSQL に変えても、概念・論理モデルはほぼ流用できる |
| 検討漏れを段階的に見つけられる | 概念で気づかなかった関係を論理段階で気づく、など |
設計プロセスは反復的
実際の設計は、概念 → 論理 → 物理と一方通行に進むわけではなく、問題を発見したら戻る 反復的なプロセスです。
たとえば実装中に「あれ、これ業務上 1 対多じゃなくて多対多じゃないか?」と気づいたら、概念設計まで戻って関係を見直します。これは失敗ではなく、自然な設計プロセスの一部です。
- 概念設計の段階で業務担当者と必ず会話する。資料だけ読んで進めると認識ズレが残る
- 論理設計の段階で正規化を意識する (第 11 章)。「あとで直そう」と思っても直しにくい
- 物理設計では実際のデータ量・アクセスパターンを意識する。1000 件しか入らないテーブルにパーティションは不要、毎秒 1000 件書き込むテーブルなら最初から考慮
演習
あなたが社内 SNS の DB 設計を任されたとします。次の作業はそれぞれ概念設計 / 論理設計 / 物理設計 のどの段階に該当するでしょうか?
- 「投稿」と「コメント」と「ユーザー」の関係を ER 図で整理する
postsテーブルの本文カラムをTEXT型にする- 投稿テーブルを第 3 正規形まで整理し、外部キーを設定する
- 投稿の検索を高速化するため
created_atにインデックスを作る - 業務担当者にヒアリングして「投稿に画像が複数添付されることがある」と確認する
- PostgreSQL と MySQL のどちらを使うか決める
解答例
| 番号 | 段階 | 理由 |
|---|---|---|
| 1. ER 図で関係整理 | 概念設計 | エンティティと関係性の整理。データ型などはまだ気にしない |
| 2. TEXT 型を決める | 物理設計 | DBMS の具体的なデータ型の決定 |
| 3. 第 3 正規化 + 外部キー | 論理設計 | 表 (リレーション) のレベルでの正規化と参照関係 |
| 4. インデックス作成 | 物理設計 | 性能のための物理的な最適化 |
| 5. 業務ヒアリング | 概念設計 | エンティティと関係を発見する作業 |
| 6. DBMS 選定 | 物理設計 | 実装プラットフォームの決定 |
ありがちな間違い: 1 と 5 を「論理設計」と思い込むこと。論理設計は「すでに見つかったエンティティを表として整理する」段階で、新しいエンティティの発見は概念設計の責務です。
あなたが Twitter のような SNS を設計中、論理設計の段階で次の問題に気づきました。
「フォロー」関係を
users.following_user_idsというカラム (フォロー先 ID の配列) で持とうとしているが、これだと「フォロー解除」のときに配列から消すロジックが複雑で、フォロー数のカウントもarray_length(following_user_ids)のような関数を使うことになる。
戻るべき段階はどこで、何を見直すべきでしょうか?
解答例
戻るべき段階: 論理設計 (場合によっては概念設計)。
見直すべきこと: 「フォロー」関係を users テーブル内の配列カラムでなく、独立した中間テーブル follows (follower_id, following_id) として表現する。これは「多対多の関係」(ユーザーは複数のユーザーをフォローし、複数のユーザーからフォローされる) で、中間テーブルで表現するのが正攻法 (第 14 章 多対多 で詳述)。
CREATE TABLE follows (
follower_id INTEGER NOT NULL REFERENCES users(id),
following_id INTEGER NOT NULL REFERENCES users(id),
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (follower_id, following_id),
CHECK (follower_id <> following_id) -- 自分自身はフォローできない
);
なぜそうなるか:
- 配列カラムは「正規化されていない」(第 1 正規形を満たさない) 設計で、検索 / 更新 / 集計のすべてで非効率
- 中間テーブルなら
WHERE following_id = ?で「誰にフォローされているか」を高速に検索できる - フォロー解除は
DELETE FROM follows WHERE follower_id = ? AND following_id = ?で 1 行削除するだけ
ありがちな間違い: 「データが少ないから配列で十分」と判断すること。フォロー機能は将来必ず性能要求が上がり、配列設計は数千フォロワーで破綻します。最初から多対多で設計するのが安全です。
別解: グラフデータベース (Neo4j など) を使う選択肢もあるが、Twitter 規模でなければ RDB + 中間テーブルで十分対応できます。
まとめ
この章で学んだことを整理します。
- データベース設計はシステム開発全体の設計フェーズに位置する
- 抽象から具体へ「概念設計 → 論理設計 → 物理設計」の 3 段階で進める
- 各段階の成果物: 概念 ER 図 → 論理モデル (正規化済テーブル群) → CREATE TABLE 文
- 設計は反復的 — 問題に気づいたら適切な段階まで戻って見直す
次章では、設計の中核となる「キー」の概念 (主キー・外部キー・候補キー・複合キー) を詳しく扱います。