STEP 7:正規化とは何か

📐 STEP 7: 正規化とは何か

データの冗長性と異常を排除する、正規化の基本を学ぼう

📋 このステップで学ぶこと
  • 正規化とは何か、なぜ必要なのか
  • 正規化の歴史と背景
  • データの冗長性問題
  • 更新異常、挿入異常、削除異常とは
  • 正規化のメリットとデメリット
  • 非正規化が必要な場面

学習時間の目安: 2時間 | 前提知識: STEP 1-6修了

🎯 1. 正規化とは?

基礎理論編(STEP 1〜6)の次のステップ

STEP 1〜6では、データベース設計の基礎を学びました。エンティティ、ER図、データ型、主キー/外部キー、命名規則…。これらを使ってテーブルを設計できるようになりました。

しかし、「テーブルを作れる」ことと「良いテーブルを設計できる」ことは違います。このSTEP 7からは、正規化編として、データの冗長性を排除し、整合性を保つ設計手法を学びます。

正規化の定義

📝 正規化とは

正規化(Normalization)=データの冗長性(重複)を排除し、データの整合性を保つためにテーブルを適切に分割すること

正規化は「整理整頓」のようなものです。
部屋が散らかっていると、同じものがあちこちにある(重複)、どこに何があるかわからない(混乱)、片付けが大変。
整理整頓すれば、同じものは1箇所にまとめ、管理しやすくなります。

正規化の目的

1. データの冗長性を排除

同じデータの重複をなくす

2. データの整合性を保証

矛盾したデータを防ぐ

3. 異常を防止

更新・挿入・削除時の異常を防ぐ

4. 保守性の向上

構造が明確で変更しやすい

📜 2. 正規化の歴史と背景

正規化を理解するうえで、その歴史的背景を知ることは重要です。

🏛️ E.F.コッド博士と関係モデル

正規化の概念は、1970年にIBMの研究者エドガー・F・コッド(Edgar F. Codd)博士によって提唱されました。

コッド博士は「A Relational Model of Data for Large Shared Data Banks」という論文で、関係モデル(リレーショナルモデル)を発表し、現代のリレーショナルデータベース(MySQL、PostgreSQL、Oracleなど)の基礎を築きました。

正規化理論の発展
年代 正規形 提唱者
1970年 第1正規形(1NF) E.F.コッド
1971年 第2正規形(2NF)、第3正規形(3NF) E.F.コッド
1974年 BCNF(ボイスコッド正規形) コッド&ボイス
1977年 第4正規形(4NF) R.ファギン
1979年 第5正規形(5NF) R.ファギン
💡 なぜ正規化が生まれたのか?

1970年代以前、データは階層型ネットワーク型のデータベースで管理されていました。しかし、これらは複雑で、データの重複や矛盾が発生しやすいという問題がありました。

コッド博士は、数学的な理論(集合論・述語論理)に基づいた「関係モデル」を提唱し、データの整合性を理論的に保証できる方法として正規化を確立しました。

つまり、正規化は「感覚的なノウハウ」ではなく、数学的に正しいことが証明された設計手法なのです。

❌ 3. データの冗長性問題

冗長性とは

⚠️ データの冗長性

冗長性(Redundancy)=同じデータが複数の場所に保存されている状態

冗長性がある悪い例

【冗長性がある:注文テーブル】 ————————————————————————— 注文ID | 顧客ID | 顧客名 | 顧客住所 | 商品ID | 商品名 | 価格 1 | C001 | 山田太郎 | 東京都新宿区 | P001 | ノートPC | 80000 2 | C001 | 山田太郎 | 東京都新宿区 | P002 | マウス | 2000 3 | C002 | 佐藤花子 | 大阪府大阪市 | P001 | ノートPC | 80000 4 | C001 | 山田太郎 | 東京都新宿区 | P003 | キーボード | 5000 【問題点】 ・「山田太郎」「東京都新宿区」が3回も重複している ・「ノートPC」「80000」も2回重複している

正規化した良い例

【正規化後:顧客テーブル】 ——————————— 顧客ID | 顧客名 | 顧客住所 C001 | 山田太郎 | 東京都新宿区 C002 | 佐藤花子 | 大阪府大阪市 【正規化後:商品テーブル】 ——————————— 商品ID | 商品名 | 価格 P001 | ノートPC | 80000 P002 | マウス | 2000 P003 | キーボード | 5000 【正規化後:注文テーブル】 ——————————— 注文ID | 顧客ID | 商品ID 1 | C001 | P001 2 | C001 | P002 3 | C002 | P001 4 | C001 | P003 【改善点】 ・各情報は1箇所にだけ保存される ・重複がなくなり、整合性が保たれる

⚠️ 4. 3つの異常(Anomaly)

正規化されていないテーブルでは、3つの異常が発生します。これらは、データの操作(更新・挿入・削除)時に問題を引き起こします。

1. 更新異常(Update Anomaly)

❌ 更新異常とは

データを更新する際に、複数箇所を更新する必要があるため、更新漏れによりデータの矛盾が発生する問題

【更新異常の例】 山田太郎が引っ越した場合、3箇所すべてを更新する必要がある 注文ID | 顧客名 | 顧客住所 1 | 山田太郎 | 東京都新宿区 ← 更新1 2 | 山田太郎 | 東京都新宿区 ← 更新2 4 | 山田太郎 | 東京都新宿区 ← 更新3 もし1箇所だけ更新を忘れると… 注文ID | 顧客名 | 顧客住所 1 | 山田太郎 | 神奈川県横浜市 ← 更新済み 2 | 山田太郎 | 東京都新宿区 ← 更新漏れ!矛盾発生 4 | 山田太郎 | 神奈川県横浜市 ← 更新済み

2. 挿入異常(Insert Anomaly)

❌ 挿入異常とは

関連データがないと、新しいデータを登録できない問題

【挿入異常の例】 新しい商品「モニター」を登録したいが、注文がないと登録できない! 注文ID | 顧客ID | 商品ID | 商品名 | 価格 1 | C001 | P001 | ノートPC | 80000 2 | C001 | P002 | マウス | 2000 ??? | ??? | P004 | モニター | 30000 ← 注文IDと顧客IDがないと登録できない! 正規化していれば、商品テーブルに直接登録可能: 商品ID | 商品名 | 価格 P004 | モニター | 30000 ← 問題なく登録できる

3. 削除異常(Delete Anomaly)

❌ 削除異常とは

データを削除すると、本来残すべき情報まで消えてしまう問題

【削除異常の例】 注文3を削除すると、「佐藤花子」の情報が完全に消えてしまう! 注文ID | 顧客ID | 顧客名 | 顧客住所 | 商品ID 1 | C001 | 山田太郎 | 東京都新宿区 | P001 2 | C001 | 山田太郎 | 東京都新宿区 | P002 3 | C002 | 佐藤花子 | 大阪府大阪市 | P001 ← この注文を削除すると… 4 | C001 | 山田太郎 | 東京都新宿区 | P003 削除後: 注文ID | 顧客ID | 顧客名 | 顧客住所 | 商品ID 1 | C001 | 山田太郎 | 東京都新宿区 | P001 2 | C001 | 山田太郎 | 東京都新宿区 | P002 4 | C001 | 山田太郎 | 東京都新宿区 | P003 → 佐藤花子の顧客情報が完全に失われた!
💡 3つの異常のまとめ
異常 問題 正規化で解決
更新異常 複数箇所の更新が必要で、更新漏れが発生 データは1箇所に保存
挿入異常 関連データがないと登録できない 独立したテーブルに分離
削除異常 削除時に必要な情報まで消える 独立したテーブルに分離

✅ 5. 正規化のメリット

✅ 正規化のメリット
  1. データの整合性:同じデータは1箇所だけに保存されるため、矛盾が発生しない
  2. 3つの異常の防止:更新・挿入・削除時の問題を防げる
  3. ストレージ効率:重複データがなくなり、ディスク使用量が減る
  4. 保守性の向上:テーブル構造が明確で、変更しやすい
  5. 拡張性の向上:新しい機能追加時も、既存テーブルへの影響が少ない

❌ 6. 正規化のデメリット

⚠️ 正規化のデメリット
  1. クエリが複雑:テーブルが分割されるため、JOINが必要になる
  2. パフォーマンス低下の可能性:複数テーブルの結合処理にコストがかかる
  3. テーブル数の増加:管理するテーブルが増える

具体例:クエリの複雑さ

非正規化テーブル(JOINなし)
— 注文と顧客情報を取得(シンプル) SELECT 注文ID, 顧客名, 商品名, 価格 FROM orders WHERE 顧客ID = ‘C001’;
正規化テーブル(JOIN必要)
— 注文と顧客情報を取得(JOIN必要) SELECT o.注文ID, c.顧客名, p.商品名, p.価格 FROM orders o JOIN customers c ON o.顧客ID = c.顧客ID JOIN products p ON o.商品ID = p.商品ID WHERE o.顧客ID = ‘C001’;
💡 デメリットへの対処

正規化のデメリットは、以下の方法で対処できます:

適切なインデックスを作成してJOINを高速化
ビューを使ってよく使うJOINをまとめる
キャッシュを活用して読み取りを高速化
✅ 必要に応じて部分的に非正規化する

⚖️ 7. 非正規化が必要な場面

すべてを正規化すれば良いわけではありません。場合によっては、意図的に非正規化することもあります。

非正規化が有効な場面

1. 集計テーブル(サマリーテーブル)

毎回集計するのが遅い場合、集計結果を保存

— 非正規化:売上集計テーブル CREATE TABLE daily_sales_summary ( date DATE PRIMARY KEY, total_amount DECIMAL(12, 2), — 重複データ order_count INT, — 重複データ customer_count INT — 重複データ ); — 毎日の集計結果を保存(高速に取得できる)
2. 頻繁にアクセスされるデータ

JOINのコストが高い場合、重複を許容

— 非正規化:商品テーブルにカテゴリ名を保存 CREATE TABLE products ( product_id INT PRIMARY KEY, product_name VARCHAR(200), category_id INT, category_name VARCHAR(100), — 重複データ price DECIMAL(10, 2) ); — JOINせずに商品とカテゴリ名を同時に取得できる
3. 読み取り専用のデータ

更新異常の心配がないデータ(過去の履歴など)

— 非正規化:注文履歴(過去のデータは変更しない) CREATE TABLE order_history ( order_id INT PRIMARY KEY, customer_name VARCHAR(100), — その時の顧客名 product_name VARCHAR(200), — その時の商品名 unit_price DECIMAL(10, 2), — その時の価格 quantity INT, order_date DATE ); — 過去の注文は「その時の情報」として保存
💡 非正規化の判断基準
  1. パフォーマンス問題が本当にあるか?実際に計測して確認
  2. インデックスで解決できないか?非正規化の前に試す
  3. 更新異常のリスクを理解しているか?整合性の維持が難しくなる
  4. キャッシュやビューで代用できないか?別の方法も検討

結論:基本は正規化。パフォーマンス問題が明確な場合のみ、非正規化を検討する。

📊 8. 正規化のレベル(概要)

正規化には、第1正規形、第2正規形、第3正規形などのレベルがあります。

📋 正規化の段階
正規形 内容 学習STEP
第1正規形(1NF) 繰り返し項目を排除し、各セルに1つの値だけを持つ STEP 8
第2正規形(2NF) 部分関数従属性を排除する STEP 9
第3正規形(3NF) 推移的関数従属性を排除する STEP 10
BCNF、4NF、5NF さらに高度な正規化 STEP 11
🎯 実務での正規化レベル

実務では、第3正規形(3NF)までを目指すのが一般的です。
それ以上の正規化は、特殊な場合を除いて不要なことが多いです。

次のSTEP 8から、各正規形を詳しく学んでいきましょう!

📝 STEP 7 のまとめ

✅ このステップで学んだこと
  • 正規化とは、データの冗長性を排除し、整合性を保つためにテーブルを分割すること
  • 正規化は1970年にE.F.コッド博士が提唱した、数学的に裏付けられた設計手法
  • 冗長性:同じデータが複数の場所に保存されている状態
  • 3つの異常:更新異常、挿入異常、削除異常
  • 正規化のメリット:整合性、異常の防止、ストレージ効率、保守性
  • 正規化のデメリット:クエリが複雑、パフォーマンス低下の可能性
  • 非正規化:パフォーマンス問題が明確な場合のみ検討
  • 実務では第3正規形まで目指すのが一般的
💡 重要ポイント

正規化は、データベース設計の最も重要な概念の1つです。

正規化することで:
✅ データの整合性が保たれる
3つの異常を防げる
保守性が向上する

次のSTEP 8からは、第1正規形、第2正規形、第3正規形を具体的に学んでいきます!

📝 練習問題

問題 1 基礎

正規化の目的を3つ挙げてください。

【解答例】
  1. データの冗長性を排除:同じデータの重複をなくす
  2. データの整合性を保証:矛盾したデータを防ぐ
  3. 異常を防止:更新異常、挿入異常、削除異常を防ぐ
問題 2 基礎

正規化の概念を提唱した人物は誰ですか?また、それは何年のことですか?

【解答】

E.F.コッド(Edgar F. Codd)博士1970年に提唱しました。

コッド博士はIBMの研究者で、「関係モデル(リレーショナルモデル)」を発表し、現代のリレーショナルデータベースの基礎を築きました。

問題 3 基礎

更新異常、挿入異常、削除異常とは何か、それぞれ簡単に説明してください。

【解答】

更新異常:データを更新する際に、複数箇所を更新する必要があり、更新漏れでデータの矛盾が発生する問題。

挿入異常:関連データがないと、新しいデータを登録できない問題。

削除異常:データを削除すると、本来残すべき情報まで消えてしまう問題。

問題 4 応用

以下のテーブルにはどんな問題がありますか?3つの異常の観点から説明してください。

社員テーブル ——————————————————— 社員ID | 社員名 | 部署名 | 部署電話番号 1 | 山田太郎 | 営業部 | 03-1234-5678 2 | 佐藤花子 | 営業部 | 03-1234-5678 3 | 鈴木一郎 | 開発部 | 03-9876-5432 4 | 田中次郎 | 営業部 | 03-1234-5678
【問題点】
  1. データの冗長性:「営業部」と「03-1234-5678」が3回重複
  2. 更新異常:営業部の電話番号が変わったら、3箇所を更新する必要がある。1箇所でも更新漏れがあると矛盾が発生
  3. 挿入異常:新しい部署「人事部」を作っても、所属する社員がいないと部署情報を登録できない
  4. 削除異常:鈴木一郎(社員ID: 3)を削除すると、開発部の部署情報も完全に消えてしまう

改善案:部署テーブルと社員テーブルに分割する

問題 5 応用

問題4のテーブルを正規化してください。どのようにテーブルを分割すればよいですか?

【解答】
【部署テーブル】 ——————————— 部署ID | 部署名 | 部署電話番号 D001 | 営業部 | 03-1234-5678 D002 | 開発部 | 03-9876-5432 【社員テーブル】 ——————————— 社員ID | 社員名 | 部署ID 1 | 山田太郎 | D001 2 | 佐藤花子 | D001 3 | 鈴木一郎 | D002 4 | 田中次郎 | D001

改善点:
✅ 部署情報は1箇所にだけ保存される(冗長性解消)
✅ 電話番号変更時は1箇所だけ更新すればOK(更新異常解消)
✅ 社員がいなくても部署を登録できる(挿入異常解消)
✅ 社員を削除しても部署情報は残る(削除異常解消)

問題 6 応用

非正規化を検討すべき場面を3つ挙げ、それぞれなぜ非正規化が有効か説明してください。

【解答例】
  1. 集計テーブル(サマリーテーブル)
    毎回大量のデータを集計するのは時間がかかるため、日次や月次の集計結果を別テーブルに保存しておくことで、レポート表示が高速化される
  2. 頻繁にアクセスされるデータ
    多数のテーブルをJOINするクエリが頻繁に実行される場合、よく使う情報を1つのテーブルにまとめることで、JOINのコストを削減できる
  3. 読み取り専用のデータ(履歴データ)
    注文履歴のように過去のデータは変更されないため、更新異常の心配がない。注文時点の商品名や価格を記録しておくことで、価格変更後も当時の情報を参照できる

重要:いずれの場合も、基本となる正規化されたテーブルは必ず維持します。

問題 7 発展

正規化のデメリットを踏まえて、なぜ正規化が重要なのか説明してください。

【解答例】

正規化にはクエリが複雑になる、パフォーマンスが低下する可能性があるというデメリットがあります。しかし、それ以上にデータの整合性を保つことが重要です。

データの矛盾や異常は、システムの信頼性に直結します。例えば、顧客の住所が複数の場所で異なる値を持っていたら、どれが正しいのかわからなくなります。これは業務上の重大な問題につながります。

パフォーマンスの問題はインデックス、キャッシュ、ビューなどで対処できますが、データの整合性が失われると取り返しがつきません

そのため、まずは正規化でデータの整合性を確保し、パフォーマンス問題が実際に発生した場合にのみ、部分的に非正規化を検討するのが正しいアプローチです。

問題 8 発展

以下のテーブルについて、(1)問題点を指摘し、(2)正規化したテーブル設計を提案してください。

図書館の貸出テーブル ———————————————————————————- 貸出ID | 会員ID | 会員名 | 会員住所 | 書籍ID | 書籍名 | 著者名 | 貸出日 1 | M001 | 山田太郎 | 東京都新宿区 | B001 | DB入門 | 田中花子 | 2025-01-10 2 | M001 | 山田太郎 | 東京都新宿区 | B002 | SQL実践 | 鈴木一郎 | 2025-01-12 3 | M002 | 佐藤花子 | 大阪府大阪市 | B001 | DB入門 | 田中花子 | 2025-01-15 4 | M001 | 山田太郎 | 東京都新宿区 | B003 | Python入門 | 田中花子 | 2025-01-18
【(1) 問題点】
  • 冗長性:会員情報(山田太郎、東京都新宿区)が3回、書籍情報(DB入門、田中花子)が2回重複
  • 更新異常:会員の住所変更時に複数箇所を更新する必要がある
  • 挿入異常:新しい書籍を登録したいが、貸出がないと登録できない
  • 削除異常:貸出ID: 3を削除すると、会員M002(佐藤花子)の情報が消える
【(2) 正規化したテーブル設計】
【会員テーブル】 ——————————— 会員ID | 会員名 | 会員住所 M001 | 山田太郎 | 東京都新宿区 M002 | 佐藤花子 | 大阪府大阪市 【書籍テーブル】 ——————————— 書籍ID | 書籍名 | 著者名 B001 | DB入門 | 田中花子 B002 | SQL実践 | 鈴木一郎 B003 | Python入門 | 田中花子 【貸出テーブル】 ——————————— 貸出ID | 会員ID | 書籍ID | 貸出日 1 | M001 | B001 | 2025-01-10 2 | M001 | B002 | 2025-01-12 3 | M002 | B001 | 2025-01-15 4 | M001 | B003 | 2025-01-18

改善点:
✅ 会員情報、書籍情報はそれぞれ1箇所に保存
✅ 住所変更は会員テーブルだけ更新すればOK
✅ 貸出なしでも書籍を登録できる
✅ 貸出削除しても会員・書籍情報は残る

❓ よくある質問

Q1: 正規化は必ず行わないといけませんか?

基本的には「はい」です。正規化しないと、データの整合性が保てず、3つの異常が発生します。ただし、パフォーマンス問題が明確な場合や、読み取り専用のデータは例外的に非正規化を検討します。

Q2: どこまで正規化すればいいですか?

実務では第3正規形(3NF)まで目指すのが一般的です。BCNF、第4正規形、第5正規形は、特殊なケースでのみ必要です。まずは第3正規形を目指しましょう。

Q3: 正規化すると必ずパフォーマンスが悪くなりますか?

いいえ、必ずしもそうではありません。正規化するとテーブルが小さくなりメモリに乗りやすくなったり、更新が速くなったりするメリットもあります。適切なインデックスを貼れば、多くの場合は問題ありません。

Q4: 正規化と非正規化、どちらを優先すべきですか?

まず正規化を行い、必要に応じて非正規化を検討します。「最適化は早すぎる最適化の根源である」という格言の通り、まずは正しい設計を優先し、パフォーマンス問題は実際に発生してから対処しましょう。

Q5: 実務でよく見る「正規化されていないテーブル」の例はありますか?

はい、よくあります。例えば、Excelからそのままインポートしたテーブル、レガシーシステムのテーブル、急いで作ったプロトタイプなどです。「1つのカラムにカンマ区切りで複数の値」「同じ情報が何度も重複」「1つのテーブルに全部詰め込む」などが典型的な例です。

Q6: 正規化は「理論」だと聞きましたが、実務で本当に役立ちますか?

絶対に役立ちます。正規化は数学的理論に基づいていますが、その目的は極めて実践的です。データの整合性を保ち、メンテナンスを容易にし、バグを減らします。理論を知らなくても「なんとなく」良い設計はできますが、理論を理解していればなぜそう設計すべきかを説明でき、より確実に良い設計ができます。

📝

学習メモ

データベース設計・データモデリング - Step 7

📋 過去のメモ一覧
#artnasekai #学習メモ
LINE