Instiq
第2章 · データベース設計と正規化·v1.0.0·更新 2026/7/10·読了目安 約17分

変更要約: 初版

2.2関数従属と正規化の理論

この節の要点

属性間の依存関係を表す関数従属、複合キーの一部だけに依存する部分関数従属、非キー属性を経由して間接的に依存する推移的関数従属、そしてこれらを段階的に排除することで更新時異常を防ぐ第1正規形第2正規形第3正規形を、実務の更新時異常の除去という設計判断として学びます。

正規化は「理論のための理論」ではなく、スキーマに潜む更新時異常(同じ事実を複数箇所に書く羽目になり、更新漏れ・矛盾・不要なNULLが発生する問題)を取り除くための実務的な手続きです。DB設計者は、目の前のスキーマがどんな更新時異常を起こしうるかを見抜き、それを解消するのに必要十分な正規化の段階を判断しなければなりません。この節では、正規化の土台となる関数従属の考え方から、第1〜第3正規形がそれぞれどの異常を取り除くのかを学びます。

2.2.1関数従属の基礎

  • 関数従属(X→Y)=属性(の組)Xの値が決まれば、属性Yの値が一意に決まるという関係。例えば「社員ID→氏名」は、社員IDが決まれば氏名が一意に決まるため関数従属が成立する。
  • 完全関数従属=複合キーXの全体に対してYが関数従属し、Xの真部分集合には従属しない状態。部分関数従属=複合キーXの一部だけにYが従属してしまっている状態(例:複合キー(社員ID,プロジェクトID)に対し、社員の氏名は社員IDだけで決まってしまう)。
  • 推移的関数従属=X→Y かつ Y→Z が成立し、結果としてX→Zとなるが、Zが非キー属性Yを経由して間接的にXに従属している状態(例:社員ID→部署コード→部署名、という連鎖で社員IDから部署名が間接的に決まる)。

2.2.2第1正規形と第2正規形

  • 第1正規形(1NF)=1つの列(セル)に複数の値を詰め込む繰返し項目を排除し、すべての属性が単一の値(原子値)のみを持つ状態。繰返し項目を残したままだと、特定の値を条件にした検索・更新が列全体の文字列解析を要する非効率な設計になる。
  • 第2正規形(2NF)=1NFを満たした上で、部分関数従属を排除した状態(非キー属性が複合キーの全体に完全関数従属する)。部分関数従属が残っていると、複合キーの一部の値だけを更新したいのに他方の値も一緒に管理せざるを得ず、更新時異常(同じ事実の重複格納・更新漏れ)が起きる。

2.2.3第3正規形と推移的関数従属の除去

  • 第3正規形(3NF)=2NFを満たした上で、推移的関数従属を排除した状態(非キー属性が他の非キー属性を経由してキーに従属することがない)。推移的関数従属が残っていると、間に挟まる非キー属性(部署コードなど)が変わらない限り重複して格納される情報(部署名)に矛盾が生じうる。
  • 正規化を進めるほど更新時異常は減るが、表が増えてSQLでのJOIN回数が増え、参照性能は低下する。このトレードオフを踏まえ、更新頻度が高く整合性が重要な業務データは正規化を優先し、参照中心で更新がほぼ発生しないデータは非正規化(次節・第5節)を検討するという判断が実務では必要になる。
試験ポイント

「1NF=繰返し項目の排除」「2NF=部分関数従属の排除(複合キー全体への完全関数従属)」「3NF=推移的関数従属の排除(非キー属性経由の間接依存を断つ)」が最頻出です。「部分関数従属」と「推移的関数従属」は混同されやすいので、部分=複合キーの一部にのみ従属/推移=非キー属性を経由した間接従属という軸の違いを必ず区別しましょう。

あるプロジェクト管理システムの設計者が、次のような1つの表で運用されているスキーマの見直しを依頼されました:「プロジェクト参画」表(社員ID, プロジェクトID, 社員氏名, 部署コード, 部署名, 参画役割)、主キーは複合キー(社員ID, プロジェクトID)です。まず「社員氏名」に着目すると、これは社員IDだけで決まり、プロジェクトIDには依存しません——部分関数従属です。この状態では、ある社員が3つのプロジェクトに参画していれば同じ氏名が3行に重複し、氏名を変更する際に3行すべてを更新しなければ矛盾(更新時異常)が生じます。次に「部署名」に着目すると、これは社員ID→部署コード→部署名という連鎖で決まっており、社員IDから部署名への推移的関数従属が存在します。ある部署の名称が変更された場合、その部署に所属する全社員の全参画行の部署名を漏れなく更新しなければ矛盾が生じる、これも更新時異常です。この2つを解消するには、まず2NF化として「社員」表(社員ID, 社員氏名, 部署コード)を分離し、部分関数従属していた氏名を社員IDのみに依存する形へ切り出します。続いて3NF化として「部署」表(部署コード, 部署名)をさらに分離し、部署名を部署コードのみに依存する形へ切り出します。結果として「プロジェクト参画」表には(社員ID, プロジェクトID, 参画役割)のみが残り、更新時異常は解消されますが、社員の氏名や部署名を得るには複数表のJOINが必要になります。ここで設計者は、社員のプロジェクト参画は頻繁に発生し社員異動も日常的に起きるため、整合性を優先して正規化を進める判断が正しいと結論づけました。JOINコストの増加は、後の性能設計(インデックス設計等)で対処すべき別の問題として切り分けます。

正規形排除する対象防ぐ更新時異常
第1正規形(1NF)繰返し項目値ごとの検索・更新が非効率になる問題
第2正規形(2NF)部分関数従属複合キーの一部にのみ従属する属性の重複と更新漏れ
第3正規形(3NF)推移的関数従属非キー属性経由の間接依存による重複と更新漏れ
注意

ひっかけ: 「部分関数従属と推移的関数従属は同じ問題である」は誤りです——部分関数従属は複合キーの一部にのみ従属する問題(2NFで解消)、推移的関数従属は非キー属性を経由して間接的に従属する問題(3NFで解消)という別の階層の問題です。また「正規化は常に高い次数まで進めるべき」も誤りで、JOINコスト増による性能劣化とのトレードオフを踏まえ、更新頻度や整合性要件に応じて必要十分な段階で止める判断が必要です。

関数従属と第1〜第3正規形の図。
異常を除く分解

2.2.4この節のまとめ

  • 関数従属(X→Y)が正規化の土台。部分関数従属=複合キーの一部にのみ従属、推移的関数従属=非キー属性経由の間接従属
  • 1NF=繰返し項目の排除、2NF=部分関数従属の排除、3NF=推移的関数従属の排除、と段階的に更新時異常を除去する
  • 正規化はJOINコスト増とのトレードオフ。更新頻度・整合性要件に応じて必要十分な段階で止める判断が実務では重要

進捗の記録にはログインが必要です。

理解度チェック

(軽い確認用)

Q1. 「プロジェクト参画」表(社員ID, プロジェクトID, 社員氏名, 参画役割)は複合キー(社員ID, プロジェクトID)を持つ。社員氏名は社員IDだけで決まりプロジェクトIDには依存しない。この表で今後起こりうる更新時異常として最も適切なものはどれか。

Q2. 前問の表をさらに調べると、部署名が「社員ID→部署コード→部署名」という連鎖で決まっており、社員IDから部署名への推移的関数従属が存在することが判明した。この推移的関数従属を排除するために取るべき対応として最も適切なものはどれか。

Q3. あるデータ基盤担当者が、参照専用で更新がほぼ発生しない集計用のレポートテーブルに対しても、第3正規形まで厳格に正規化すべきだと主張している。この主張の妥当性として最も適切な評価はどれか。

理解度を確認第2章「データベース設計と正規化」の問題を解く