正規化
データの重複をなくし、1つの事実を1か所だけに置くようにテーブルを分割する設計手法。更新の不整合(更新異常)を防ぐのが目的。
- 1.正規化は“1つの事実は1か所だけ”にして、重複と更新異常をなくすテーブル設計の手法。
- 2.第1正規形(繰り返し列をなくす)→ 第2(主キー全体に依存)→ 第3(主キー以外に依存しない)と段階的に整える。
- 3.速度のためにあえて重複を残す“非正規化”は最後の手段。まず正しく正規化し、計測してから崩す。
なぜ必要? — 重複が生む「更新異常」
たとえば1枚の表に、注文・顧客・商品をぜんぶ詰め込んだとします。
| 注文ID | 顧客名 | 顧客住所 | 商品名 | 単価 |
|---|---|---|---|---|
| 1 | 田中 | 東京都… | ノートPC | 120000 |
| 2 | 田中 | 東京都… | マウス | 3000 |
「田中」の住所が2行にコピーされています。この重複が、3つの異常を引き起こします。
- 更新異常: 田中の住所変更で、片方の行だけ直すと食い違う。
- 挿入異常: まだ注文のない新商品を、注文行なしでは登録できない。
- 削除異常: 最後の注文を消すと、その顧客や商品の情報まで消えてしまう。
正規化は、これらを設計の段階で起きないようにする作業です。
道具:主キーと外部キー
正規化は「テーブルを分けて、関連で結び直す」作業なので、2つのキーが土台になります。
| キー | 役割 | ひとことで |
|---|---|---|
| 主キー(PK) | その行を一意に特定する列 | 重複・NULL 不可の“行の住所” |
| 外部キー(FK) | 他テーブルの主キーを指す列 | テーブル同士をつなぐ“参照リンク” |
外部キーには参照整合性(存在しない顧客IDの注文は作れない、等)を DB に守らせる役割もあります。詳しくはテーブルの結合(JOIN)で、分けたテーブルを再びつなぐ方法を扱います。
第1〜第3正規形をやさしく
実務でまず目指すのは第3正規形(3NF)まで。段階的に条件が積み重なります。
| 正規形 | 条件をひとことで | 違反の例 |
|---|---|---|
| 第1正規形(1NF) | 1セルに1つの値。繰り返し列をなくす | 商品列に「PC, マウス」と詰め込む |
| 第2正規形(2NF) | 主キー“全体”に依存させる(部分従属を排除) | 複合キーの一部だけで決まる列がある |
| 第3正規形(3NF) | 主キー以外の列に依存させない(推移従属を排除) | 郵便番号から住所が決まる |
1NF:1つのセルに1つの値
タグ 列に "赤, 大, 限定" のようにカンマ区切りで詰めるのは 1NF 違反。検索も集計も難しくなります。値を1つにし、複数あるなら別テーブルに切り出します。
2NF:主キー全体で決まるようにする
主キーが (注文ID, 商品ID) の複合キーなのに、商品名 が 商品ID だけで決まる場合、これは「部分従属」。商品名は商品テーブルへ移します。
3NF:芋づる式の依存を断つ
顧客ID(主キー)→ 郵便番号 → 住所 のように、主キー以外の列を経由して決まる関係(推移従属)も分離します。郵便番号と住所の対応は別テーブルへ。
-- 3NF へ分割した例:事実が1か所だけになる
CREATE TABLE customers (
customer_id INT PRIMARY KEY, -- 主キー
name TEXT NOT NULL,
address TEXT NOT NULL -- 顧客の住所はここ“だけ”
);
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT NOT NULL REFERENCES customers(customer_id), -- 外部キー
ordered_at TIMESTAMP NOT NULL DEFAULT now()
);
住所は customers の1行だけ。引っ越しても1か所直せば全注文に反映され、食い違いが起きません。
覚え方
3NF までの定番の語呂は 「the key, the whole key, and nothing but the key(キーに、キー全体に、キー以外の何物にも依らず)」。1NF=キーで識別、2NF=キー全体に依存、3NF=キー以外には依存しない、の3段と対応します。
非正規化:あえて重複させる
正規化を進めると、表示のたびに多くのテーブルを JOIN する必要が出て、読み取りが遅くなることがあります。そこで意図的に重複を持たせて速度を取るのが非正規化です。
| 観点 | 正規化 | 非正規化 |
|---|---|---|
| 事実の置き場所 | 1か所だけ(重複なし) | あえて複数に複製 |
| 更新 | 1か所直せばよい・整合しやすい | 全コピーを直す必要・崩れやすい |
| 読み取り | JOIN が増えがち | JOIN が減り高速になりやすい |
| 向く場面 | 更新が多い基幹データ | 読み取り中心・集計・キャッシュ |
具体例としては、注文表に「単価×数量」を毎回計算せず 合計金額 列を持たせる、集計済みのサマリーテーブルを別に用意する、などがあります。
速くなる保証はなく、整合性を守る責任が自分(アプリ側)に移るのが非正規化の代償です。順番は「① まず正しく正規化 → ② 実際に遅いと計測で確認 → ③ そこだけ崩す」。推測で先に崩すと、バグの温床と不要な複雑さだけが残ります。
何でも1枚の表に詰め込む設計(God table)は、一見シンプルでも更新異常の温床です。重複した値が増えるほど「どれが正しいの?」が分からなくなります。まずは分けて、必要ならインデックスで読み取りを補うのが定石。
どこまでやる?
- 多くの業務システムでは 3NF を基本に、表示が重い箇所だけ非正規化、が現実的なバランス。
- 一方、NoSQL(RDB との違い)では、結合を避けるためあえて非正規化(埋め込み)を前提に設計することも多い。正規化は“常に正義”ではなく、更新と読み取りのどちらを重く見るかで選ぶ設計判断です。
データベース Article
正規化を実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
データベース
比較で見る軸
難易度: intermediate / カテゴリ: データベース / タグ数: 3
導入後に効く点
第1正規形(繰り返し列をなくす)→ 第2(主キー全体に依存)→ 第3(主キー以外に依存しない)と段階的に整える。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- intermediate
- カテゴリ
- データベース
- タグ数
- 3
判断チェックリスト
- 自社の用途が「データベース / 設計」に近いか確認する。
- 強みである「正規化は“1つの事実は1か所だけ”にして、重複と更新異常をなくすテーブル設計の手法。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。