正規化とは?データベース設計の基本をわかりやすく解説
正規化とは
正規化とは、データの重複や矛盾をなくすために、テーブルの構造を整理する設計手法のことです。「1つの情報は1か所にだけ存在させる」というのが基本的な考え方で、データベース設計の土台となる知識です。
言葉だけだとイメージしづらいので、まずは正規化されていない(=非正規形の)テーブルの問題点から見ていきましょう。
非正規形の問題点
以下のような「注文テーブル」があったとします。
orders
+----+--------+----------------+------------+-------+
| id | user | user_email | product | price |
+----+--------+----------------+------------+-------+
| 1 | 田中太郎 | tanaka@ex.com | ノートPC | 120000|
| 2 | 田中太郎 | tanaka@ex.com | マウス | 3000 |
| 3 | 鈴木花子 | suzuki@ex.com | ノートPC | 120000|
+----+--------+----------------+------------+-------+このテーブルには次のような問題があります。
- 更新異常:田中太郎さんのメールアドレスが変わったら、1行だけでなく該当する全行を更新しなければならない。更新漏れが起きると矛盾したデータが残る
- 挿入異常:まだ何も注文していない新規ユーザーの情報を登録したくても、注文がないと行自体を作れない
- 削除異常:ある注文を削除すると、それがそのユーザーの最後の注文だった場合、ユーザー情報ごと消えてしまう
第1正規形:繰り返し項目をなくす
1つのセルに複数の値を詰め込まず、1セル1値にすることが第1正規形の条件です。例えば「担当科目:数学,英語,理科」のようにカンマ区切りで複数値を1セルに入れるのはNGです。行を分けて1セル1値にします。
第2正規形:部分関数従属をなくす
複合主キー(複数カラムの組み合わせで一意になるキー)を持つテーブルで、キーの一部だけに従属するカラムを別テーブルに分離します。先ほどの注文テーブルであれば、ユーザー情報(名前・メールアドレス)は「注文ID」ではなく「ユーザーID」だけで決まる情報なので、usersテーブルとして切り出します。
-- users テーブル
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
email TEXT
);
-- orders テーブル(user_idで参照するだけ)
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
user_id INTEGER,
product TEXT,
price INTEGER
);第3正規形:推移的関数従属をなくす
キーを介さずに、あるカラムが別の非キーカラムに従属している状態(推移的従属)も分離します。例えば「部署ID」から「部署名」がわかる場合、部署名をemployeesテーブルに持たせるのではなく、departmentsテーブルに分離してIDだけで参照します。
CREATE TABLE departments (
id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE employees (
id INTEGER PRIMARY KEY,
name TEXT,
department_id INTEGER
);
-- 部署名が必要な時はJOINで取得する
SELECT e.name, d.name AS department
FROM employees e
JOIN departments d ON e.department_id = d.id;ここまでで、実務上は「正規化は完了」と考えられることがほとんどです(第4・第5正規形はより特殊なケース向けなので、まずは第3正規形までを目標にすれば十分です)。
正規化しすぎるとどうなるか(トレードオフ)
正規化を進めるほどテーブル数は増え、データを取得するために必要なJOINの数も増えていきます。JOINが多いクエリは書くのも読むのも大変になり、パフォーマンスにも影響します。
そのため実務では、集計処理を高速化したいレポート用のテーブルなどで、あえて正規化を崩して重複を許容する「非正規化」を行うこともあります。正規化は「絶対の正解」ではなく、整合性と扱いやすさのバランスを取るための考え方だと理解しておきましょう。
まとめ
- 正規化とは、データの重複・矛盾をなくすためのテーブル設計手法
- 非正規形は更新異常・挿入異常・削除異常を引き起こしやすい
- 第1正規形:1セル1値にする
- 第2正規形:複合キーの一部にしか従属しないカラムを分離する
- 第3正規形:キーを介さない従属関係にあるカラムを分離する
- 正規化しすぎるとJOINが増えるため、実務ではバランスを見て判断する
