0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DB正規化をざっくり復習する

0
Posted at

はじめに

DB設計をしていると、「正規化」という言葉が出てきます。

私自身も過去に正規化を意識してDB設計をしたことがありますが、しばらく経つと

  • 第1正規形って何だっけ?
  • 第2正規形と第3正規形の違いは?
  • そもそも、なぜ正規化するんだっけ?

のようになっていたので、久しぶりに復習してみました。

正規化とは?

ざっくり言うと、

データの重複や不整合を減らすために、テーブルを適切に分割・整理すること

です。

例えば、注文情報を次のように管理していたとします。

注文ID 顧客名 顧客住所 商品名
1 田中太郎 福岡市中央区 ノートPC
2 田中太郎 福岡市中央区 マウス

この状態で田中さんが引っ越すと、住所を複数のレコードで更新する必要があります。

もし更新漏れがあると、

注文ID 顧客名 顧客住所 商品名
1 田中太郎 福岡市早良区 ノートPC
2 田中太郎 福岡市中央区 マウス

のように、同じ顧客なのに住所が違うという状態になってしまいます。

そこで、顧客情報と注文情報などを別々に管理します。

  • customers:顧客情報
  • orders:注文情報
  • products:商品情報

これが正規化の基本的なイメージです。

なお、理論上は第3正規形より先の正規形も定義されていますが、実際のDB設計では第3正規形までの考え方がよく使われます。

第1正規形

例えば、顧客の電話番号を次のように管理していたとします。

顧客ID 顧客名 電話番号
1 田中太郎 090-XXXX-XXXX, 080-XXXX-XXXX
2 佐藤花子 070-XXXX-XXXX

この場合、田中さんの「電話番号」という1つのセルに、2つの電話番号が入っています。

このような構造だと、特定の電話番号を検索したり、電話番号を1件ずつ扱ったりするのが難しくなります。

そこで、電話番号を1つずつ別のレコードとして管理します。

顧客ID 顧客名 電話番号
1 田中太郎 090-XXXX-XXXX
1 田中太郎 080-XXXX-XXXX
2 佐藤花子 070-XXXX-XXXX

このように、1つのセルには1つの値だけを入れるようにします。

第1正規形は、

1つのセルに複数の値を入れない

と覚えておけばOKです。

第2正規形

例えば、学生の履修情報を次のように管理しているとします。

このテーブルでは、学生IDと授業IDを複合主キーとして組み合わせることで、「誰がどの授業を履修したのか」を特定できます。

学生ID 授業ID 学生名 授業名 成績
1 A 田中太郎 数学 優
1 B 田中太郎 英語 良
2 B 佐藤花子 英語 可

ここで、学生名に注目してみます。

学生ID 授業ID 学生名
1 A 田中太郎
1 B 田中太郎
2 B 佐藤花子

同じ学生IDの行では、学生名も同じです。

つまり、学生名を管理するために授業IDは必要ありません。

授業名も同じです。

学生ID 授業ID 授業名
1 A 数学
1 B 英語
2 B 英語

同じ授業IDの行では、授業名も同じです。

つまり、授業名を管理するために学生IDは必要ありません。

このように、複合主キーの一部だけで決まるデータがある状態を「部分関数従属」といいます。

そこで、学生・授業・履修をそれぞれ分けます。

  • students
    • id
    • name
  • courses
    • id
    • name
  • enrollments
    • student_id
    • course_id
    • grade

こうすることで、学生名や授業名を履修情報のたびに持たせる必要がなくなります。

第2正規形は、

複合主キーの一部だけで決まるデータがあれば分離する

と覚えておけばOKです。

第3正規形

例えば、社員情報を次のように管理しているとします。

このテーブルでは、社員IDを主キーとします。

社員ID 社員名 部署ID 部署名
1 田中太郎 D01 営業部
2 佐藤花子 D02 開発部
3 山田一郎 D01 営業部

部署名に注目してみます。

部署ID = D01なら「営業部」、部署ID = D02なら「開発部」です。

つまり、部署名は社員IDから直接決まるのではなく、部署IDによって決まる情報です。

そのため、社員情報の中に部署IDと部署名の両方を持たせる必要はありません。

このように、部署名が主キーである社員IDから直接決まるのではなく、部署IDを介して決まる関係を「推移的関数従属」といいます。

そこで、社員と部署をそれぞれ分けます。

  • employees
    • id
    • name
    • department_id
  • departments
    • id
    • name

こうすることで、部署名を社員情報の中に繰り返し持たせる必要がなくなります。

第3正規形は、

主キー以外のカラムを介して決まるデータを分離する

と覚えておけばOKです。

正規化しすぎればいいわけではない

正規化の目的は、とにかくテーブルを細かく分割することではありません。

データの重複や不整合を減らしつつ、扱いやすい構造にすることが目的です。

一方で、読み取り性能やクエリの複雑さなどを考慮して、あえてデータを重複して持つ非正規化を行うこともあります。

そのため実際のDB設計では、「どこまで正規化するか」 を考えることになります。

まとめ

  • 第1正規形 → 1セル1データ
  • 第2正規形 → 部分関数従属をなくす
  • 第3正規形 → 推移的関数従属をなくす
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?