第4章 正規化
更新日:2025年12月28日
この章を音声で聴く
1. 正規化の目的
1.1 データ冗長性
データ冗長性(Data Redundancy)とは、同じデータが複数箇所に重複して格納されている状態を指す。冗長性は以下の問題を引き起こす。
Table 1. 冗長性のあるテーブル例(非正規形)
| 注文ID | 顧客名 | 顧客住所 | 商品名 | 単価 |
|---|---|---|---|---|
| 1001 | 田中太郎 | 東京都新宿区 | りんご | 200 |
| 1002 | 田中太郎 | 東京都新宿区 | みかん | 150 |
| 1003 | 鈴木花子 | 大阪府大阪市 | りんご | 200 |
上記テーブルでは、「田中太郎」の住所が2回、「りんご」の単価が2回格納されている。これがデータ冗長性である。
1.2 更新異常
データ冗長性は、3種類の更新異常(Update Anomaly)を引き起こす。
Table 2. 更新異常の種類
| 異常の種類 | 説明 | 例 |
|---|---|---|
| 挿入異常 | 不要な情報がないと挿入できない | 注文がない顧客を登録できない |
| 更新異常 | 一部の更新漏れで不整合が発生 | 田中太郎の住所を1行だけ変更すると矛盾 |
| 削除異常 | 削除時に必要な情報も消える | 注文1003を削除すると鈴木花子の情報が消失 |
正規化の主な目的は、(1) データ冗長性の排除、(2) 更新異常の防止、(3) データ整合性の向上、(4) ストレージの効率化である。ただし、過度な正規化はJOIN操作の増加によるパフォーマンス低下を招く可能性がある。
2. 関数従属性
関数従属性(Functional Dependency)は、正規化理論の基礎となる概念である。属性Xの値が決まると属性Yの値が一意に決まる関係を「YはXに関数従属する」といい、X → Y と表記する。
Table 3. 関数従属性の例
| 関数従属性 | 意味 | 説明 |
|---|---|---|
| 社員ID → 氏名 | 社員IDが決まれば氏名が決まる | 1人の社員に1つの氏名 |
| 社員ID → 部署ID | 社員IDが決まれば部署IDが決まる | 1人の社員は1つの部署に所属 |
| 部署ID → 部署名 | 部署IDが決まれば部署名が決まる | 1つの部署に1つの名前 |
| {注文ID, 商品ID} → 数量 | 注文IDと商品IDで数量が決まる | 複合キーへの従属 |
完全関数従属と部分関数従属
完全関数従属:複合キー全体に従属(例:{注文ID, 商品ID} → 数量)
部分関数従属:複合キーの一部に従属(例:{注文ID, 商品ID} のうち注文ID → 顧客名)
推移的関数従属
X → Y かつ Y → Z のとき、X → Z を推移的関数従属という。例:社員ID → 部署ID → 部署名
3. 正規形
Fig. 1. 正規化のプロセス
3.1 第1正規形
第1正規形(1NF: First Normal Form)は、すべての属性が原子的(atomic)であることを要求する。つまり、繰り返し項目や複数の値を含むセルがあってはならない。
Table 4. 非正規形から第1正規形への変換
| 非正規形(1NFに違反) | ||
|---|---|---|
| 注文ID | 顧客名 | 商品リスト |
| 1001 | 田中太郎 | りんご, みかん, バナナ |
↓ 第1正規形に変換
| 第1正規形(1NF) | ||
|---|---|---|
| 注文ID | 顧客名 | 商品 |
| 1001 | 田中太郎 | りんご |
| 1001 | 田中太郎 | みかん |
| 1001 | 田中太郎 | バナナ |
3.2 第2正規形
第2正規形(2NF: Second Normal Form)は、第1正規形であり、かつすべての非キー属性が主キーに完全関数従属することを要求する。部分関数従属を排除する。
Table 5. 第1正規形から第2正規形への変換
| 第1正規形(2NFに違反)- 部分関数従属あり | ||||
|---|---|---|---|---|
| 注文ID | 商品ID | 数量 | 顧客名 | 商品名 |
| 1001 | P01 | 3 | 田中太郎 | りんご |
主キー: {注文ID, 商品ID}
部分関数従属: 注文ID → 顧客名(商品IDに依存しない)
部分関数従属: 商品ID → 商品名(注文IDに依存しない)
↓ 第2正規形に分解
-- 注文テーブル
CREATE TABLE orders (
order_id INTEGER PRIMARY KEY,
customer_name VARCHAR(100)
);
-- 商品テーブル
CREATE TABLE products (
product_id INTEGER PRIMARY KEY,
product_name VARCHAR(100)
);
-- 注文明細テーブル
CREATE TABLE order_details (
order_id INTEGER,
product_id INTEGER,
quantity INTEGER,
PRIMARY KEY (order_id, product_id)
);
3.3 第3正規形
第3正規形(3NF: Third Normal Form)は、第2正規形であり、かつすべての非キー属性が主キーに推移的関数従属しないことを要求する。
Table 6. 第2正規形から第3正規形への変換
| 第2正規形(3NFに違反)- 推移的関数従属あり | |||
|---|---|---|---|
| 社員ID | 氏名 | 部署ID | 部署名 |
| E001 | 田中太郎 | D01 | 営業部 |
| E002 | 鈴木花子 | D01 | 営業部 |
推移的関数従属: 社員ID → 部署ID → 部署名
↓ 第3正規形に分解
-- 社員テーブル
CREATE TABLE employees (
employee_id VARCHAR(10) PRIMARY KEY,
name VARCHAR(100),
department_id VARCHAR(10)
);
-- 部署テーブル
CREATE TABLE departments (
department_id VARCHAR(10) PRIMARY KEY,
department_name VARCHAR(100)
);
3.4 BCNF
ボイス・コッド正規形(BCNF: Boyce-Codd Normal Form)は、第3正規形のより厳密な形である。すべての関数従属において、決定項(左辺)がスーパーキーでなければならない。
Table 7. 第3正規形とBCNFの違い
| 正規形 | 条件 |
|---|---|
| 3NF | 非キー属性が主キーに推移的従属しない |
| BCNF | すべての関数従属の決定項がスーパーキー |
実務では第3正規形まで正規化することが一般的である。BCNFは理論的には望ましいが、分解により情報の損失が発生する場合がある。また、第4正規形(4NF)、第5正規形(5NF)も存在するが、実務での適用は稀である。
4. 正規化の限界
正規化には利点が多いが、以下の点に注意が必要である。
Table 8. 正規化の利点と欠点
| 利点 | 欠点 |
|---|---|
| データ冗長性の排除 | JOIN操作の増加 |
| 更新異常の防止 | クエリの複雑化 |
| ストレージ効率の向上 | パフォーマンス低下の可能性 |
| データ整合性の向上 | 設計の複雑化 |
非正規化(Denormalization)
パフォーマンスを優先する場合、意図的にテーブルを非正規化することがある。特に、読み取りが多く更新が少ないシステムでは、JOINを減らすために冗長性を許容することがある。
正規化の実践指針
Step 1:まず第3正規形まで正規化する
Step 2:パフォーマンステストを実施
Step 3:ボトルネックがJOINにある場合のみ、部分的に非正規化を検討
Step 4:非正規化する場合は、整合性維持の仕組み(トリガー等)を検討
5. まとめ
Table 9. 正規形の一覧
| 正規形 | 要件 | 排除するもの |
|---|---|---|
| 1NF | すべての属性が原子的 | 繰り返し項目、複合値 |
| 2NF | 1NF + 部分関数従属なし | 複合キーの一部への従属 |
| 3NF | 2NF + 推移的関数従属なし | 非キー間の従属関係 |
| BCNF | すべての決定項がスーパーキー | キー以外からの関数従属 |
本コンテンツは2025年12月時点の情報に基づいて作成されています。正規化理論はE.F.Coddにより1970年代に確立されました。実務での適用は要件とパフォーマンスを考慮して判断してください。