Loading Context

よみこみちゅう...

Blog

論理設計① 正規化の概要

2024.12.11

本記事の目的

正規化とは何か、種類ごとに理解する。 また、正規化がなぜ必要なのか、その必要性を理解する。

正規化とは?

正規化とは、データベース設計において「データの冗長性を減らし、一貫性を保つ」ための手法です。 具体的には、「同じ情報が複数の場所に重複して記録される」ことを防ぐために行われます。 例えば、顧客の名前や住所が複数の箇所に記録されている場合、情報の変更時にミスが発生しやすくなり、不整合(データの矛盾)が生じるリスクがあります。 これにより、データの信頼性が損なわれるリスクがあります。 こうした問題を解決するために、「データを適切なテーブルに分割する」手法を用いることが正規化の本質と言えるでしょう。

たとえば、正規化には以下のような段階的なプロセスがあります。 ※ 正規化は第5正規形まで存在しますが、ここでは主に重要とされる第1正規形から第3正規形までを解説します。

第1正規形

第1正規形のルールは、「1つのセルには単一のデータのみを含む」というものです。 文章だけでは「?」という感じかもなので、実例をみて説明します。

第1正規化されていない例

ショップテーブル

ショップIDショップ名支払い方法
1A商店現金,クレジット
2B商店現金,バーコード決済

このように、支払い方法のカラムに複数のデータが入っています。

第1正規化している例

ショップテーブル

ショップIDショップ名支払い方法
1A商店現金
1A商店クレジット
2B商店現金
2B商店バーコード決済

のようになります。 第一正規化を行うことで、データの一貫性が向上し、データの検索や更新が容易になります。 このように、1つのセルに1つだけの値が含まれている状態を「スカラ値」と呼びます。 反対に、1つのセルに複数の値が含まれている状態を「非スカラ値」と呼びます。

テーブルを増やすのが面倒で、カンマ区切りでデータを保持していた時代が僕にもありました。今回改めて勉強して、深く反省します。。

第2正規形

第2正規化では、第一正規化を満たした上で、部分関数従属を排除することが目的です。 こちらも例を参考に見ていきます。

第2正規化されていない例

学生テーブル

学校ID学校名学生ID学生名学年学科ID学科名
S001A学校C001山田1G001経済
S001A学校C002田中2G002外国
S002B学校C003佐藤2G003教育

このテーブルの主キーは、「学校ID」「学生ID」になります。 つまり、他のカラムはこれらのキーに従属するはずなのですが、「学校名」だけ主キーの一部の「学校ID」にのみ従属しています。 この関係を「部分従属」と呼び、第2正規化ではこの部分従属を排除するのが目的です。 ※ テーブルのすべての非キー属性が主キーのすべての要素に依存している状態を「完全従属」と呼びます。

第2正規化している例

学生テーブル

学校ID学生ID学生名学年学科ID学科名
S001C001山田1G001経済
S001C002田中2G002外国
S002C003佐藤2G003教育

学校テーブル

学校ID学校名
S001A学校
S001A学校
S002B学校

このようにテーブルを分けることによって、部分従属を排除することができます。 これによって完全従属となり、第2正規形となりました!

ん、、あんまりメリットわからない?

と思ったそこのあなた、第2正規化されていない状態では、大きな欠点が2つあります。

一つ目は、データの整合性を保てないことです。 第2正規化されていない状態のテーブルについて考えてみます。例えば、先ほどの「A学校」の名前が「C学校」に変更される場合を想定します。この際、運用ミスにより、該当するレコードのうち一部しか更新しなかったとします。

その結果、同じ「学校ID」を持つレコード間で「学校名」に不整合が生じる可能性があります。このような状態では、同じ学校であるにもかかわらず、異なる名前が記録されてしまい、データの信頼性が損なわれます。

そして二つ目が、学生がいない学校が登録できないというところです。 新たに「C学校」という学校のデータを登録したい場合を考えてみます。まだ学生がいないため、学生IDを入力するデータが存在しません。しかし、元の形では「学生ID」が主キーの一部であり、NOT NULL制約があるため、「C学校」を登録することができません。このような状況では、学校の登録が学生の登録に依存してしまい、不便さを感じる場面が多くなります。

こういった欠点を解消するための、第2正規化でした。

第3正規形

第3正規化では、第2正規化までを満たした上で、推移的関数従属を排除することが目的です。 こちらも例を参考に見ていきます。

第3正規化されていない例

学生テーブル(第2正規形)

学校ID学生ID学生名学年学科ID学科名
S001C001山田1G001経済
S001C002田中2G002外国
S002C003佐藤2G003教育

第2正規化までは、主キーに関する従属を整理してきました。一方、第3正規化では、主キー以外の従属関係を整理することが目的となります。

例えば、この例で考えると、一つだけ特筆すべき従属関係があります。それが、{学科ID} -> {学科名} という関係です。このように、主キー以外のカラム間で発生する従属関係を「推移的関数従属」と呼びます。

第3正規化を適用することで、このような推移的関数従属を解消し、データ構造をより効率的で整合性の高い形にすることができます。 第3正規化は第2正規化と似ていて、こちらも別テーブルで管理することによって推移的関数従属を解消できます。

第3正規化している例

学生テーブル

学校ID学生ID学生名学年学科ID
S001C001山田1G001
S001C002田中2G002
S002C003佐藤2G003

学科テーブル

学科ID学科名
G001経済
G002外国
G003教育

こんな感じです! 3正規化されていない状態では、学科に一人も学生がいない場合、その学科を登録することができません。このような状況では、学科情報の登録が学生情報に依存してしまうため、不便さが生じます。 このような欠点を補うために、第3正規化では学科情報を独立したテーブルとして分離します。これにより、学科情報を学生情報とは関係なく管理できるようになり、柔軟かつ効率的なデータ登録と管理が可能になります。

終わり

以上が、第1正規化から第3正規化までの学習内容でした。 しっかりと意識できていた箇所もありましたが、「ここは注意しないといけないな」と気づかされる点もありました。とても有意義な振り返りができたと思います。

実は、第4正規化や第5正規化についても触れたかったのですが、予想以上に内容が膨らんでしまったため、今回は割愛しました。 いつか機会があれば、第4正規化や第5正規化についても取り上げてみたいと思います!

それでは、ここまでお付き合いいただきありがとうございました!

CONTACT

「これって頼める?」みたいなざっくりしたご相談もOKです!
気になることがあれば、いつでもお気軽にご連絡ください。

SNS