MySQL の正規化(第1〜第3正規形)
正規化はリレーショナルデータベース設計の基礎理論で、データの冗長性を排除し、更新時の不整合を防ぐための手法です。実務で求められるのは主に第1〜第3正規形までで、これらを理解しておけば大半のテーブル設計に対応できます。
非正規形(正規化前)
まず、正規化されていない状態を見てみましょう。以下は1つのテーブルにすべての情報を詰め込んだ例です。
-- 非正規形:1つのセルに複数の値が入っている
-- | 注文ID | 顧客名 | 商品名 | 単価 |
-- |--------|---------|-----------------|--------------|
-- | 1 | 田中 | ペン, ノート | 100, 300 |
-- | 2 | 鈴木 | 消しゴム | 80 |商品名と単価に複数の値がカンマ区切りで入っており、検索や集計が非常に困難です。この状態を解消するのが正規化の第一歩になります。
第1正規形(1NF)
第1正規形の条件は「各セルに格納する値が原子的(これ以上分割できない単一の値)であること」です。
CREATE TABLE orders_1nf (
order_id INT,
customer_name VARCHAR(50),
product_name VARCHAR(100),
unit_price DECIMAL(10,2),
PRIMARY KEY (order_id, product_name)
);
-- 1行1商品に分解される
-- | order_id | customer_name | product_name | unit_price |
-- |----------|---------------|--------------|------------|
-- | 1 | 田中 | ペン | 100 |
-- | 1 | 田中 | ノート | 300 |
-- | 2 | 鈴木 | 消しゴム | 80 |これで各セルが1つの値を持つようになりましたが、customer_name が注文ごとに繰り返されるという冗長性が残っています。
第2正規形(2NF)
第2正規形の条件は「第1正規形を満たし、かつ部分関数従属がないこと」です。部分関数従属とは、複合主キーの一部だけで決まるカラムが存在する状態を指します。
customer_name は order_id だけで決まるのに、複合主キー(order_id, product_name)の一部にしか依存していない。これが部分関数従属。
order_id だけで決まるカラムを別テーブルに分離する。注文テーブルと注文明細テーブルに分けることで解消される。
-- 注文テーブル
CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_name VARCHAR(50) NOT NULL
);
-- 注文明細テーブル
CREATE TABLE order_items (
order_id INT,
product_name VARCHAR(100),
unit_price DECIMAL(10,2) NOT NULL,
PRIMARY KEY (order_id, product_name),
FOREIGN KEY (order_id) REFERENCES orders(order_id)
);第3正規形(3NF)
第3正規形の条件は「第2正規形を満たし、かつ推移的関数従属がないこと」です。推移的関数従属とは、主キー以外のカラムを経由して決まるカラムが存在する状態です。
-- 第2正規形だが第3正規形ではない例
-- | employee_id | department_id | department_name |
-- department_name は department_id で決まる(推移的関数従属)
-- 第3正規形に分解
CREATE TABLE departments (
department_id INT PRIMARY KEY,
department_name VARCHAR(100) NOT NULL
);
CREATE TABLE employees (
employee_id INT PRIMARY KEY,
department_id INT NOT NULL,
FOREIGN KEY (department_id) REFERENCES departments(department_id)
);department_name が employees テーブルに残っていると、部署名を変更するときに全社員レコードを更新する必要があり、更新漏れによる不整合が起きるリスクがあります。
正規化の流れ
非正規形:セルに複数値がある
第1正規形:各セルを原子的にする
第2正規形:部分関数従属を排除する
第3正規形:推移的関数従属を排除する
実務での注意点
理論的にはボイス・コッド正規形(BCNF)や第4・第5正規形もありますが、実務で意識するのは第3正規形までで十分です。過度な正規化はテーブル数の増加と JOIN の多発を招き、かえってパフォーマンスを悪化させます。正規化はあくまで設計の出発点であり、パフォーマンス要件に応じて意図的に非正規化する判断も必要になります。



