なぜ実務のデータベース設計は「第3正規形」で止まるのか|高次正規化の存在意義とトレードオフの境界線

Computerプログラミング

パーマリンク

教科書と現場のギャップ

データベースの設計を学び始めた頃、情報処理技術者試験の参考書やリレーショナルモデルの専門書を開いて、違和感を覚えた経験はないでしょうか。

教科書には「第1正規形」「第2正規形」「第3正規形」に始まり、「ボイス・コッド正規形(BCNF)」「第4正規形」「第5正規形」、果ては「第6正規形」までが整然と解説されています。しかし、いざ実務のプロジェクトに参画し、ER図やテーブル定義書を眺めてみると…

「実務のテーブル設計は、基本的に第3正規形(3NF)までしかないな…」

なぜデータベース理論には第6正規形まで存在するにもかかわらず、現場では「第3正規形」が事実上の標準であり終着点となっているのでしょうか。 正規化とは何か、各正規形の目的、そしてなぜ基本的に第3正規形までで十分とされるのかを以下に整理します。気になるたびに調べては忘れてしまうので…。


第3正規形は「費用対効果(ROI)」の分岐点

最初に、各正規形が何を目的として定義されているのかを整理します。本記事では、正規化の目的を**「データ冗長性に起因する更新時不整合(挿入・更新・削除の異常)を排除すること」**と定義します。

各正規形の段階と対象とする依存関係

正規形 主な要件 排除される問題(更新異常) 実務での遭遇頻度
第1正規形 (1NF) 属性値がスカラ(単一値)であり、繰り返しグループを持たない カンマ区切り文字列や配列による検索不能・更新の複雑化 必須
第2正規形 (2NF) 1NFを満たし、すべての非キー属性が主キーに完全関数従属する(部分関数従属の排除) 複合主キーの一部だけに依存するデータの重複と更新異常 必須
第3正規形 (3NF) 2NFを満たし、主キー以外の属性への関数従属を持たない(推移的関数従属の排除) 郵便番号→住所のような、非キー属性間の連鎖による更新異常 必須(標準)
ボイス・コッド正規形 (BCNF) 3NFを満たし、すべての決定項が候補キーである 主キーの一部が非キー属性に従属する特殊な異常 たまに考慮
第4正規形 (4NF) BCNFを満たし、独立した多値従属性を持たない 1つのエンティティに対する独立した1対N関係の直積爆発 稀(設計で自然回避)
第5正規形 (5NF) 4NFを満たし、自明でない結合従属性を持たない 3者以上の複合キーにおける循環的制約による異常 極めて稀
第6正規形 (6NF) 5NFを満たし、自明な結合従属性しか存在しない(主キー+非キー属性1つのみ) 属性単位の独立した履歴・更新管理の欠如 特殊用途(DWH等)

※表内の分類(正規形の要件)は執筆時点(2026年8月)の一般的なリレーショナルデータベース理論に基づきます。ただし「実務での遭遇頻度」は私個人の経験に基づく目安であり、業種・システム規模により異なると思われます。

3NFで大半の更新異常が消える

3NFを達成すると、テーブル内のすべての非キー属性は「主キーのみ」に依存する状態になります(有名なフレーズである "Every non-key attribute must provide a fact about the key, the whole key, and nothing but the key" の状態です)。

私がこれまで経験してきた不整合の多くは、代表的に以下の3パターンに分類できます。

  1. 挿入異常: 親データ(顧客情報など)が存在しないと子データ(注文明細など)を登録できない
  2. 更新異常: 顧客の住所が変わった際、過去の注文レコード数万件をすべてUPDATEしなければ不整合が起きる
  3. 削除異常: 最後の注文履歴を削除したら、顧客自体のマスターデータまで消えてしまう

これらはすべて「1NF〜3NF」の正規化プロセスによって解消されます。つまり、3NFまで到達した時点で、体感としてリレーショナルモデルが約束する整合性の恩恵の大半を享受できるのです。


第4・第5正規形が実務で滅多に出てこない理由

では、なぜ第4正規形(4NF)や第5正規形(5NF)は実務の設計現場で話題に上りにくいのでしょうか。

結論から言えば、4NFや5NFが対象とする「多値従属性」や「結合従属性」は、通常の業務ドメインでは滅多に現れないか、概念モデリングの段階で自然と別エンティティ(中間テーブル)に分割されるからだと捉えています。

多値従属性(4NFの対象)の具体例

例えば、「社員」「保有スキル(複数)」「話せる言語(複数)」という3つの属性を持つテーブルを考えてみましょう。 1人の社員が複数のスキルを持ち、複数の言語を話せるとします。

【非4NFのテーブル例】
社員ID | スキル   | 言語
------+---------+------
E001  | Python  | 日本語
E001  | Python  | 英語
E001  | Rust    | 日本語
E001  | Rust    | 英語

スキルと言語の間には何の関係もないにもかかわらず、1行にまとめようとすると直積(2スキル × 2言語 = 4行)が発生し、新しいスキルを追加するたびに言語の数だけ行をINSERTしなければなりません。これが多値従属性による異常です。

しかし、実際の業務設計では「社員-スキル関係」テーブルと「社員-言語関係」テーブルを最初から独立した交差テーブルとして定義するのが自然です。設計者が「多値従属性の理論」を意識していなくても、エンティティの抽出を適切に行っていれば、結果として4NFを満たす設計に自然と落ち着きます。

Note

第5正規形(5NF)はさらに特殊で、「AとB」「BとC」「CとA」という3つのペアが存在するときにのみ「A・B・C」の組み合わせが成立するという、3者間の循環的な制約(結合従属性)を扱います。現実のビジネス要件でこのような条件が具体的に問題化する場面は限られています。


正規化とJOINコストのトレードオフ

正規化を進めることには明確なメリットがありますが、同時に無視できない代償が伴います。それが「クエリ実行時のJOINコスト」と「設計・実装の認知的負荷」です。

flowchart LR
    subgraph S1["正規化(高次)"]
        A["書き込み整合性 最適化"]
        B["テーブル数 増加"]
        C["JOINコスト 増加"]
    end
    subgraph S2["非正規化(低次)"]
        D["読み込み性能 最適化"]
        E["データ重複 許容"]
        F["更新不整合リスク 増加"]
    end
    A --- D
  1. Write(更新クエリ)の観点:
    • 正規化されているほど、データの重複がなく、ロックの競合範囲が小さくなり、INSERTやUPDATEが安全かつ高速に行えます。
  2. Read(参照クエリ)の観点:
    • 正規化が進むほど、1つの意味ある画面(例: 注文詳細画面)を表示するために必要なJOINの数が増加します。
    • インデックスの効かせ方が難しくなり、RDBMSのクエリオプティマイザの負荷が増大します。

高次正規化(4NF〜6NF)を突き詰めると、テーブルはバラバラに細分化されます。しかし、現代のWebアプリケーションのトラフィックは、一般に経験則として「参照(Read)が9割以上、更新(Write)が1割未満」と言われるReadヘビーな特性を持つことが多いです。

もっとも、金融取引や在庫管理のように整合性要求が極めて高くWrite比率も無視できないドメインでは、追加のJOINコストを払ってでも正規化を優先する判断は合理的です。しかし一般的なReadヘビーなWebアプリケーションでは、整合性の向上という「わずかな追加リターン」のために、毎秒数万回実行されるSELECTクエリのJOIN負荷という「大きな恒常的コスト」を支払うのは、エンジニアリングとして割に合わないケースが多いと考えます。


例外としての第6正規形(6NF)|時制データとAnchor Modeling

「第4正規形以降は実務で使われない」と書きましたが、実は第6正規形(6NF)だけは、特定の実務領域で脚光を浴びています。

第6正規形とは、テーブルを「主キー + 非キー属性1つのみ」になるまで徹底的に垂直分割した極限の正規形です。

【6NF的な分割例】
- ユーザー_氏名テーブル (ユーザーID, 氏名, 有効開始日時, 有効終了日時)
- ユーザー_住所テーブル (ユーザーID, 住所, 有効開始日時, 有効終了日時)
- ユーザー_ステータステーブル (ユーザーID, ステータス, 有効開始日時, 有効終了日時)

一見すると狂気に思える設計ですが、これが威力を発揮するのが「時制データ(Temporal Data)の厳密な履歴管理」と「データウェアハウス(DWH)」です。

Anchor Modelingという解決策

代表的な手法が、6NFをベースにしたアジャイルデータモデリング手法である「Anchor Modeling」や、それに近い履歴分割のアプローチを取る「Data Vault」です。

ビジネスにおいて、属性ごとに変更されるライフサイクルは全く異なります。

  • ユーザーの「氏名」は滅多に変わらない(年単位)
  • ユーザーの「ステータス」は頻繁に変わる(日・週単位)
  • ユーザーの「住所」は引越し時のみ変わる

これらを1つのテーブルで管理しようとすると、一部の属性が変わるたびにレコード全体を履歴テーブルにコピーするか、複雑な履歴管理カラムを持たせる必要があります。6NFのように属性ごとに独立した時系列テーブルを持たせれば、以下のメリットが得られます。

  • スキーマ変更の容易さ: 新しい属性を追加する際は、ALTER文による既存テーブルの変更を避け、新しい属性テーブルを1つ追加するだけで済む(無停止デプロイとの相性が抜群に良い)。
  • 完全な監査証跡: どの属性が、いつ、誰によって変更されたかを属性単位で完全追跡できる。
  • テーブル除去(Table Elimination): 一部のDWH/RDBMSが備えるテーブル除去(Table Elimination)機能により、「氏名」しか参照しないクエリに対しては「住所」「ステータス」テーブルへのJOINを自動的にバイパス(除去)して高速に実行できます。
Tip

6NFは、一般的なトランザクション処理(OLTP)のWebアプリよりも、「大規模な分析基盤(OLAP)」や「法的な監査要件が極めて厳しいエンタープライズシステム」における強力な選択肢として実用されています。


実践:実務で迷わないためのデータベース設計プラクティス

これらを踏まえ、実務でデータベースを設計する際はどのような手順を踏むべきでしょうか。私が普段のシステム開発で実践している基本原則を共有します。

1. 「第3正規形(3NF)」で論理設計を完成させる

最初からパフォーマンスを過度に心配して非正規化(カラムの重複持ちやサマリーの埋め込み)を行ってはいけません。 まずはドメインモデルを忠実に表現し、第3正規形(必要であればBCNF)まで徹底的に正規化します。これにより、システムのデータモデルの「あるべき論理構造」が明確になります。

2. ワークロードの性質(OLTP vs OLAP)で分離する

  • OLTP(WebアプリケーションのプライマリDB):
    • 基本は第3正規形を維持。
    • トランザクション整合性と更新のスムーズさを最優先にする。
  • OLAP(分析用DWH・レポーティング):
    • スタースキーマやスノーフレークスキーマによる非正規化、あるいは要件に応じてAnchor Modeling(6NF)を採用する。
    • OLTPとOLAPを同じデータベースインスタンスで両立させようとしないことが重要です。

3. 計測に基づいて「選択的非正規化」を検討する

開発が進み、ステージング環境や実負荷テストでスロークエリが発生した段階で、初めて非正規化を検討します。

Warning

非正規化(集計値のキャッシュカラム、結合のショートカットカラムなど)を導入する際は、必ず「更新時に整合性を担保するトリガーやトランザクション処理のコスト」を天秤にかけてください。非正規化は借金(テクニカルデット)の一種であり、利息(不整合対策の実装コスト)を払い続ける覚悟が必要です。


まとめ:正規化理論は「道具箱の目盛り」として使う

正規化とは、数字が大きければ大きいほど優れているというものではありません。

  • 1NF〜3NF: データ整合性を保つための「必須の基礎体力」
  • 4NF〜5NF: 適切なエンティティ抽出を行っていれば自然と満たされる「安全弁」
  • 6NF: 時制データや大規模DWHの柔軟性を最大化するための「特殊用途の尖った武器」

実務において第3正規形までしか使われないのは、現場のエンジニアが理論を軽視しているためではありません。「更新整合性の担保」と「クエリ実行パフォーマンス・開発保守コスト」のバランスが最も釣り合うスイートスポットが3NFだからだと考えています。

Tip

ドメインの要件(更新頻度・整合性制約)とシステムの特性(Read/Write比率)の接点を見極め、理論上の最高峰(高次正規化)に固執せず、最も費用対効果の高い設計を選択する。

データベース設計に迷ったときは、このトレードオフの境界線を思い出す!


参考資料

理論的背景

実務設計・事例