内部設計とDBMS〜正規化の考え方
概要
- 日程: Day 7 / セッション 1
- 時間: 09:30-10:00(30分)
- 形式: 座学
- ゴール: 内部設計の役割(外部設計をシステム内部でどう実現するか)とDBMSのメリット(アクセスの標準化・クエリによる高速化)を1分以内に説明でき、第一〜第三正規化の手順を伝票データの例で示せる
- 学習形式: 対話型解説、デモンストレーション
導入(5分)
昨日まで皆さんが作ってきたのは「外から見た製品の姿」でした。画面遷移図と画面仕様書、これらはユーザに見える顔です。
ところで、ユーザが「予約する」ボタンを押した瞬間、システムの内側では何が起きているでしょうか?
答えは「データを正しい形で記録する」ことです。今日からの2日間(Day 7-8)は、システムの内側=舞台裏を設計します。
設計フェーズの現在地
問いかけ:レストランで例えると、外部設計は「ホールの様子(メニュー・テーブル配置)」、内部設計は何でしょうか?
→ そう、厨房の動線・調理器具・食材の保管方法です。お客様の目には見えないけれど、これが無いと料理は出てきません。
本編(25分)
1. 内部設計とは
内部設計とは、外部設計をシステム内部でどのように実現するかを定義する作業です。要件を仕様(設計書)に変換し、システムの具体的な動作を決めます。
内部設計の成果物(2日間で作るもの)
| 成果物 | いつ作る | 役割 |
|---|---|---|
| テーブル定義書(またはファイル設計書) | Day7 Session2 | データの入れ物を決める |
| ER図 | Day7 Session3 | テーブル間の関係を見える化する |
| CRUD図 | Day8 Session2 | 機能とテーブルの対応を見える化する |
| 機能設計書 | Day8 Session3 | 機能の中身(入力チェック・ボタン動作・初期設定)を決める |
ここがポイント
- 外部設計が「何を見せるか」なら、内部設計は「どう実現するか」
- 内部設計書ができれば、明日から実装ができる状態になる
- 「設計書とコードがずれたら設計書を直す」。コードと設計書は常に同期させる
コラム:内部設計と外部設計の境界線
実は内部設計と外部設計の境界は会社や流派によって違います。ある現場では「画面仕様書」は内部設計とされ、別の現場では「DB論理設計」は外部設計とされます。本研修では「ユーザに見える=外部、見えない=内部」というシンプルな線引きを採用します。境界線にこだわるより、抜け漏れなく設計できているかが大切です。
2. DBMSについて
**DBMS(Database Management System、データベース管理システム)**とは、データを安全・高速に保存し取り出すための専用ソフトウェアです。MySQL、PostgreSQL、SQLite、Oracle などが代表例です。
ファイル保存とDBMSの違い
たとえば「会員一覧」を保存するとき、テキストファイルでもCSVでも保存はできます。ではなぜわざわざDBMSを使うのでしょうか。
| 観点 | ファイル保存 | DBMS |
|---|---|---|
| アクセス方法 | プログラムごとに自作 | SQL という標準言語で統一 |
| 検索速度 | 全件読み込みが必要 | インデックスで高速 |
| 同時アクセス | 競合しやすい | トランザクションで安全 |
| データの整合性 | プログラム任せ | 制約で守れる |
ここがポイント
- DBMSのメリットは大きく2つ。アクセスの標準化(SQL)とクエリによる高速化(インデックス・最適化)
- 本研修ではDBMSを使うチームと使わないチームの両方を想定する
- DBMSを使わないチームも、データの構造を「正規化」する考え方は同じように使う
DDLの最小例(CREATE TABLE)
DBMSではテーブルを SQL の DDL(Data Definition Language)で定義します。
CREATE TABLE members (
id INTEGER PRIMARY KEY,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
このように「カラム名」「型」「制約(NOT NULL, UNIQUE, PRIMARY KEY)」を宣言します。テーブル定義書を作るときも、この情報を表形式で書き出します。
3. 正規化〜なぜ整理するのか
正規化とは、データの重複や矛盾を防ぐためにテーブル構造を整理する作業です。第一・第二・第三と段階的に進めます。
なぜ正規化が必要なのか、悪い例から始めましょう。
正規化前:受注伝票そのままテーブル
これは現実の伝票をそのままテーブルにした例です。
| 受注ID | 受注日 | 顧客名 | 顧客住所 | 商品1 | 単価1 | 数量1 | 商品2 | 単価2 | 数量2 |
|---|---|---|---|---|---|---|---|---|---|
| 1001 | 2026/06/20 | 鈴木花子 | 東京都新宿区 | りんご | 100 | 3 | みかん | 80 | 5 |
| 1002 | 2026/06/20 | 鈴木花子 | 東京都新宿区 | バナナ | 150 | 2 |
何が起きるか
- 商品が3つになったら? 列を増やすたびにテーブル設計を変える必要がある
- 鈴木花子さんが引っ越したら? 全行を更新しないと住所が矛盾する
- 商品「りんご」の価格が変わったら? 該当行すべてを修正する必要がある
これを更新異常・挿入異常・削除異常といいます。正規化はこの異常を防ぎます。
第一正規化(1NF):繰り返し項目を排除する
ルール:1つのセルには1つの値だけ、繰り返しの列を作らない。
正規化後:受注テーブルと受注明細テーブルに分ける。
受注テーブル
| 受注ID | 受注日 | 顧客名 | 顧客住所 |
|---|---|---|---|
| 1001 | 2026/06/20 | 鈴木花子 | 東京都新宿区 |
| 1002 | 2026/06/20 | 鈴木花子 | 東京都新宿区 |
受注明細テーブル
| 受注ID | 行番号 | 商品名 | 単価 | 数量 |
|---|---|---|---|---|
| 1001 | 1 | りんご | 100 | 3 |
| 1001 | 2 | みかん | 80 | 5 |
| 1002 | 1 | バナナ | 150 | 2 |
なぜ?:商品数の制限が無くなり、構造変更なしで何個でも追加できます。
第二正規化(2NF):主キーの一部に依存する列を分離する
ルール:複合主キーの場合、主キーの一部だけに依存する列は別テーブルへ。
受注明細の主キーは「受注ID + 行番号」ですが、商品名・単価は「商品」が決まれば決まる属性です。商品テーブルを分けます。
商品テーブル
| 商品ID | 商品名 | 単価 |
|---|---|---|
| 1 | りんご | 100 |
| 2 | みかん | 80 |
| 3 | バナナ | 150 |
受注明細テーブル(修正版)
| 受注ID | 行番号 | 商品ID | 数量 |
|---|---|---|---|
| 1001 | 1 | 1 | 3 |
| 1001 | 2 | 2 | 5 |
| 1002 | 1 | 3 | 2 |
なぜ?:りんごの単価が変わっても商品テーブルを1行更新するだけで済みます。
第三正規化(3NF):主キー以外の列に依存する列を分離する
ルール:主キー以外の列によって決まる列は別テーブルへ。
受注テーブルの「顧客住所」は「顧客名(実際は顧客ID)」が決まれば決まる属性です。顧客テーブルに切り出します。
顧客テーブル
| 顧客ID | 顧客名 | 顧客住所 |
|---|---|---|
| 101 | 鈴木花子 | 東京都新宿区 |
受注テーブル(最終版)
| 受注ID | 受注日 | 顧客ID |
|---|---|---|
| 1001 | 2026/06/20 | 101 |
| 1002 | 2026/06/20 | 101 |
なぜ?:鈴木花子さんが引っ越しても、顧客テーブルを1行更新するだけで全受注に反映されます。
ここがポイント
- 第一正規化=繰り返しを無くす(縦に並べる)
- 第二正規化=主キーの一部に依存する列を分離(複合主キーがある場合)
- 第三正規化=主キー以外への依存を分離(推移的依存の排除)
- 各段階で「どの異常を防いだか」を必ず説明できるようにする
4. DBMSを使わないチームへ
開発ツールとして Unity や紙ベースのプロトタイプを選ぶチームでは DBMS を使わないかもしれません。その場合は ファイル設計書 を作ります。
ファイル設計書とは、JSON ファイルや CSV ファイルに保存するデータ構造を「ファイル名・項目・型・例」で定義したものです。正規化の考え方はそのまま使えます。「1つの JSON 配列に繰り返し項目を埋め込まない」「マスタとなるデータは別ファイルにする」と読み替えてください。
ファイル設計書の例(JSON想定)
ファイル名: orders.json
[
{
"order_id": 1001,
"order_date": "2026-06-20",
"customer_id": 101,
"details": [
{ "product_id": 1, "quantity": 3 },
{ "product_id": 2, "quantity": 5 }
]
}
]
注: details を埋め込む形は第一正規化を厳密には満たしませんが、JSON ファイル管理では実用的なパターンです。チームで「明細はネストする/別ファイルに切り出す」をルール化してください。
💬 AIに聞いてみよう
正規化のデモを自分の言葉で確認するため、AI に次のような質問をしてみましょう。
- 「受注伝票テーブルを第一正規形→第二正規形→第三正規形へ段階的に変換する例を、表で示して」
- 「私たちのチームの情報モデル『○○』を仮テーブルにしたとき、第二正規化で分離すべき列はどれか教えて」
- 「正規化しすぎることのデメリットを教えて」
- 「DBMSを使わずJSONファイルで管理する場合、正規化の考え方をどう活かせばいい?」
まとめ(5分)
今日のセッションの要点を3つに絞ります。
- 内部設計は外部設計をシステム内部でどう実現するかを決める作業
- DBMSのメリットはアクセスの標準化(SQL)と高速化(クエリ最適化)
- 正規化は更新異常・挿入異常・削除異常を防ぐためにやる。各段階で「なぜ」を説明できれば本物の理解
次のセッション(Session 2)では、自チームの情報モデルを実際に正規化し、テーブル定義書(またはファイル設計書)を作ります。
🔄 振り返りチェック
- 内部設計の役割を1文で説明できる
- DBMSのメリットを2つ挙げられる
- 第一正規化が解決する問題を例で説明できる
- 第二正規化と第三正規化の違いを説明できる
- DBMSを使わない場合の代替手段を1つ挙げられる
補足資料
- 教育要件「第5部:内部設計」(
/home/dot/public_html/materials/youken/課題解決型学習(PBL).txt) - Day4 情報モデル定義書(自チーム成果物)
- Day5-6 外部設計書(自チーム成果物)
- 参考: SQL の DDL 基本構文(CREATE TABLE / 制約)
学習ガイド
想定される質問と回答例
| 質問 | ヒント |
|---|---|
| 正規化はどこまでやればいい? | 第三正規形までで実務の大半は十分。性能のために意図的に崩す(非正規化)こともある |
| 主キーは必ず必要? | はい。行を一意に識別できないとUpdateやDeleteで意図しない行に影響する |
| 外部キーは必須? | 論理的には必要。DBMSの制約として宣言するかはチームの方針による |
| なぜ「商品名」をそのまま受注明細に残してはダメ? | 価格や名称の変更時に古い受注が新しい値に変わってしまう。受注時点の値を保持したい場合は「受注時単価」のように別列で持つ |
| DBMSを使うか使わないかはいつ決める? | プロトタイプ作成(Day10)の前に決定。技術選定はチーム計画書の一部 |
つまずきやすいポイント
| つまずきポイント | ヒント |
|---|---|
| 第二正規化と第三正規化の違いが曖昧 | 主キー全体に依存しない=2NF違反、主キー以外に依存する=3NF違反、と覚える |
| 正規化しすぎてテーブルが増えすぎる | 「業務でほぼ常に一緒に検索する項目」は無理に分けない判断もアリ |
| 既存システムのDBが正規化されていない | 歴史的経緯や性能の都合。設計時の理想と運用後の現実は別物と理解しておく |
| 受注時点の値(単価・住所)を保持したい | 「履歴を残す列」は意図的に冗長化する。これはアンチパターンではなくスナップショット設計 |
| DBMSを使わないチームが何を作ればいいか分からない | テーブル定義書の代わりに「ファイル名・項目・型・例」を表で書く。次セッションでテンプレートを示す |