データベースの正規化とは?
正規化は、同じデータの重複や更新ミスを減らすために、役割ごとに表を整理する考え方です。図で「分ける理由」から理解しましょう。
→ データベース正規化を練習する
まずは図で理解:正規化すると何が変わる?
ネットショップの注文情報を1つの表だけで管理すると、同じ顧客名や住所、商品名が何度も登場します。正規化では、それぞれの役割ごとに表を分け、IDで関連付けます。
正規化前:注文表に全部入れる
| 注文 | 顧客 | 住所 | 商品 |
|---|---|---|---|
| 001 | 田中 | 東京 | キーボード |
| 002 | 田中 | 東京 | マウス |
| 003 | 佐藤 | 大阪 | モニター |
正規化後:役割ごとに分ける
氏名
住所
顧客ID
商品ID
商品名
価格
「表を細かくすること」ではなく、同じ情報を何度も持たせず、追加・更新・削除で矛盾が起きにくい構造にすることです。
第1正規形:1セルに1つの値
まず、1つのセルに複数の値をまとめて入れないようにします。
NG
| 注文ID | 商品 |
|---|---|
| 001 | キーボード、マウス |
第1正規形
| 注文ID | 商品 |
|---|---|
| 001 | キーボード |
| 001 | マウス |
第2正規形:主キーの一部だけに依存する項目を分ける
複合主キーを持つ表では、「主キー全部」ではなく「主キーの一部」だけで決まる項目がないか確認します。
商品名は「注文ID+商品ID」がなくても、商品IDだけで決まります。そこで商品名を商品テーブルへ分けます。これが部分関数従属をなくす考え方です。
第3正規形:別の項目を経由して決まるデータを分ける
主キー以外の項目を経由して、別の項目が決まっていないか確認します。
部署名は社員IDから直接決まるのではなく、部署IDによって決まります。そのため部署IDと部署名を「部署テーブル」に分けます。
第1正規形 → 1セル1値
第2正規形 → 主キーの「一部」への依存をなくす
第3正規形 → 非キー項目を「経由」する依存をなくす
実際の仕事ではどう使う?
実務イメージたとえばECサイトでは、顧客・商品・注文を1つの巨大な表にせず、役割ごとに分けて管理します。
勤怠管理なら「社員」「部署」「勤怠」、予約システムなら「利用者」「予約」「サービス」といった具合です。資格試験だけの知識ではなく、データベース設計の土台として使われます。
正規化すればするほど良い?
必ずしもそうではありません。表を細かく分けすぎると、データ表示のたびに多くのテーブルを結合する必要があります。実務では性能や用途を考えて、あえて一部をまとめる「非正規化」を選ぶ場合もあります。
ミニ問題:どこを分ける?
社員表に「社員ID・社員名・部署ID・部署名」があります。部署IDが決まると部署名が1つに決まります。第3正規形を考えると、どのように分けるのがよいでしょう?
答えを見る
社員表:社員ID・社員名・部署ID
部署表:部署ID・部署名
「社員ID → 部署ID → 部署名」という推移的な依存を分離します。
まとめ
正規化の本質は「同じ情報を何度も持たせず、どの値が何によって決まるかを整理すること」です。まず第1〜第3正規形の違いを図でつかみ、そのあと実際の表を分ける練習をすると定着しやすくなります。
どの正規形・関数従属に当てはまるかを、自分で判断してみましょう。
実務例:部署名の変更に強い社員データを作る
社員一覧に「社員ID・社員名・部署ID・部署名」をすべて保存していると、部署名を変更するときに所属社員の全行を更新する必要があります。一部の行だけ更新し忘れると、同じ部署IDに異なる部署名が混在してしまいます。
そこで、社員表(社員ID、社員名、部署ID) と 部署表(部署ID、部署名) に分けます。部署名は部署表の1行だけ変更すればよくなります。社員表の部署IDは部署表を参照する外部キーとして扱い、参照整合性を保つ設計が一般的です。
ただし、正規化すれば必ず高速になるわけではありません。読み取り時にJOINが増える場合もあるため、性能要件に応じてインデックスや非正規化を検討します。
確認問題:部署名はどちらの表に保存する?
部署表です。部署IDに対応する部署名を一元管理します。