コンピューターサイエンス:アルゴリズム / OS / ネットワーク / DB

正規化とは何か

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

正規化とは何か

このレッスンで分かること

  • 正規化が解決する 3 つの更新異常
  • 関数従属という概念の意味
  • 1NF から 5NF までの全体像

正規化 とは

なぜ正規化が必要なのか、更新異常の概念を理解する。本レッスンでは、正規化 の基本から実際の使いどころまでを整理し、現場で迷わず使える形に落とし込みます。

正規化が必要な理由

正規化 (Normalization) とは、テーブル設計を整理して データの冗長性 を排除し、更新異常 を防ぐ手続きです。1970 年代に E.F.Codd によって体系化されました。

「テーブルを分けるなんて、JOIN が増えて遅くなるだけでは」と思うかもしれません。しかし、正規化していない設計は 3 つの異常 を引き起こし、長期運用で必ず痛い目に遭います。

3 つの更新異常

例として、注文テーブルにユーザー情報を全部書いた「ダメな設計」を考えます。

order_iduser_iduser_nameuser_emailproductamount
1100Alicealice@ex.comApple500
2100Alicealice@ex.comBanana300
3200Bobbob@ex.comCherry800

ここで起きる 3 つの異常が次のものです。

1. 更新異常 (Update Anomaly) — Alice がメアドを変えたら 2 行更新が必要。1 行でも忘れると alice@ex.com と新メアドが混在し、データ不整合になる。

2. 挿入異常 (Insertion Anomaly) — まだ注文していない新規ユーザーを登録できない。productamountNULL の行を入れるしかない。

3. 削除異常 (Deletion Anomaly) — Bob の唯一の注文を取り消すと、Bob 自身の情報も消える。

正規化はこれらを 設計レベル で解決します。

diagram (will load when visible)

実務では 3NF まで やれば十分とされ、4NF / 5NF はめったに使いません。

関数従属という考え方

正規化の中心概念が 関数従属 (Functional Dependency) です。「ある列の値が決まれば別の列の値が一意に決まる」関係を意味し、A -> B と書きます。

  • user_id -> user_name — ユーザー ID が決まれば名前は 1 つに決まる
  • (order_id, product_id) -> quantity — 注文と商品の組が決まれば数量が決まる
  • user_id -> user_email — ユーザー ID が決まればメアドは 1 つに決まる

user_id が決まれば user_name が決まる」のに、同じ user_id の行に異なる user_name が書ける状態が 冗長 であり、異常の原因です。

正規形のおおまかなイメージ

正規形排除するものひとことで言うと
1NF繰り返し項目各セルは原子値
2NF部分関数従属複合キーの一部だけに依存しない
3NF推移関数従属非キー列同士で依存しない
BCNFあらゆる関数従属主キー候補のみが他を決める
4NF多値従属独立した多値属性を分ける
5NF結合従属これ以上分解不能な最小単位

具体例で予習

先のテーブルを 3NF まで分解するとこうなります。

SQL クエリ

CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(50), email VARCHAR(100) ); CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT, FOREIGN KEY (user_id) REFERENCES users(id) ); CREATE TABLE order_items ( order_id INT, product VARCHAR(50), amount INT, PRIMARY KEY (order_id, product), FOREIGN KEY (order_id) REFERENCES orders(id) );

ユーザー情報は users に 1 行ずつ。注文は orders で参照。商品明細は order_items に展開。これで Alice のメアド変更は 1 行で済み、Bob の注文を消しても Bob 自身は残ります。

トレードオフ

正規化のデメリットは JOIN が増えて読み取りが遅くなる ことです。レポートやダッシュボード用に、あえて 1 つのテーブルに集約することを 非正規化 と呼びます。実務では「OLTP は 3NF、OLAP は非正規化」のように使い分けます。

正規化は OLTP(オンライントランザクション)の世界。非正規化は OLAP(分析)の世界。

やってみよう

  • 自分のプロジェクトの 1 番大きいテーブルを書き出し、関数従属を矢印で書いてみる
  • 「同じ値が複数行に重複している列」を探す(それが冗長性のサイン)
  • 3NF にしたときに何個のテーブルに分かれるか試算する

よくある質問

Q. なぜ正規化するのですか?

A. データの重複を排除し、更新時の不整合(更新異常・挿入異常・削除異常)を防ぐためです。第 3 正規形まで適用すると保守性が大きく上がります。一方で JOIN が増えるため、検索性能と保守性のバランスで非正規化することもあります。

Q. 1NF と 2NF の違いは?

A. 1NF は「各セルが単一値」、2NF は「主キーの一部だけに依存するカラムをテーブル分割」する形です。複合キーの片方だけに紐づく属性は別テーブルに切り出すと 2NF になります。1NF を満たさないと 2NF 以降の議論はできません。

Q. 全部正規化すれば最適ですか?

A. 理想ですが、JOIN が増えてパフォーマンスが落ちる場面では非正規化(カラム複製、計算結果のキャッシュ)も有効です。OLTP は 3NF、レポーティング用 DWH はスタースキーマ(非正規化)と、用途で使い分けるのが現代的なアプローチです。

次のレッスン

次は 第1正規形 で、なぜ正規化が必要なのか、更新異常の概念を理解する を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. 正規化とは何か の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. 正規化とは何か とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン