アバンタイトル
IT分野は範囲がとても広いです。そのため、過去問を解いていると1ページに何個も理解できない単語が出てきます。それを一気に理解しようとするのはとても骨が折れるし、やる気も続きません。
しかし、そんな時は1周まわって1つのことに徹底集中してみるのはどうでしょうか?覚えなきゃいけないことが沢山あると、終わりが見えずモチベーションが続きません。
でも、「今日はこの1つをマスターしよう!」と1つにフォーカスすればゴールが見えて、集中力も続くようになります。また、一点集中型なので理解力も深まり応用も効くようになります。
ということで、当サイトでは1点集中をコンセプトに解説を展開しています。勉強法が定まっていなかったり悩んでいる方は是非、続きをご覧になってみてはいかかでしょうか?
はじめに
今回も中二病心を刺激するワードを取り扱います。それがDB正規化(1NF,2NF,3NF)です。今までのナイキストの定理、JIS Z 8521などと比べると若干弱めですが、たまにはこんぐらいのもやってみるのもいいと思います。
ということで皆さん、今回学ぶこのフレーズに対しては、「難しそー」とか「役に立つの?」といった思考は一旦おいといて「ただかっこいいから知りたい!」というシンプルな思考でStudyしていってほしいです。
そのためにこの記事では、初心者にも超分かりやすく解説していきます。ただの試験対策、ただの退屈な勉強、という感覚ではなく、「知識として知っていたらなんかカッコいいから」という軽い気持ちでStudyしていきましょう!また、この記事はだれでも読み進められる構成になっているので、最後まで楽に進めます。そして、読み終わった頃には、「あれ?知らぬ間に理解が深まっているぞ」ということに気づくでしょう。それでは、一緒に学んでいきましょう!そして、「勉強しなきゃ!」という義務感ではなく「かっこいいから知りたい!」という単純な理由で楽しみながらStudyしていきましょう!
【ここで扱う疑問】
- DB正規化を簡単にいうと?
- DB正規化のポイントは?
- 第一正規化(1NF)ってなに?
- 第二正規化(2NF)ってなに?
- 部分的関数従属をもっと砕いて表現すると?
- 第三正規化(3NF)ってなに?
- 第三と第二の違いは?
- おまけ:用語解説
- 非キー属性ってなに?
- 部分的関数従属ってなに?
などなど、様々な疑問を当ページではスッキリ超分かりやすく解決していきます!
「第○正規形(Normal Form)」と「第○正規化(Normalization)」は、一般的に同じ意味を指しますが、文脈によって微妙に異なる使い方がされることがあります。
第○正規形(Normal Form, NF):
これはデータベース理論における概念。
第○正規化(Normalization):
これはデータベースの設計プロセスを指している。
ただし、一般的にはこれらは同じ概念を指す場合がほとんどです。そのため、当サイトでもこれら2つを混在しての解説となります。あまり、深く考えず読み進めてください!
DB正規化を簡単にいうと?
DBにおける正規化は、データの冗長性を減らし、一貫性を保つためのプロセスです。以下のポイントで説明します。
DB正規化のポイントは?
目的
: データの重複を減らし、データの更新、削除、挿入の際に生じる異常(更新異常、削除異常、挿入異常)を防ぐことです。
段階
: 正規化は複数の段階(正規形)があります。各段階は、次の段階に進むほど厳密な構造を持ちます。
- 第一正規形 (1NF): 各列が単一の値を持ち、重複するデータがないこと。
- 第二正規形 (2NF): 1NFを満たし、すべての非キー属性が主キーに完全に従属すること。
- 第三正規形 (3NF): 2NFを満たし、非キー属性が他の非キー属性に従属しないこと。
正規化のNFは「正規形 (Normal Form)」の略です。データベース設計における段階を表し、それぞれの段階がデータの整理度合いを示しています。例えば、第一正規形 (1NF)、第二正規形 (2NF)、第三正規形 (3NF) などがあります。
利点
: データの整合性が高まり、データの管理が容易になります。また、データベースのサイズが効率的に管理され、無駄なデータが減ります。
注意点
: 正規化を進めすぎると、複雑なクエリが必要になり、性能に影響を与えることがあります。そのため、バランスが重要です。
第一正規化(1NF)ってなに?
第一正規化(1NF)は、データベースのテーブルが次の条件を満たす状態を指します:
- 各列が単一の値を持つ: 各フィールドには一つの値しか入らないようにします。例えば、複数の電話番号を一つの列にカンマで区切って保存するのではなく、別々の行に分けます。
- 列が原子性を保つ: 列のデータは分割できない最小単位であること。これにより、データの整合性が保たれ、効率的なクエリが可能になります。
1NFにすることで、データの管理がしやすくなり、更新や検索が効率化されます。
例:
非正規化状態:
顧客ID | 名前 | 電話番号
-------|--------|---------------
1 | 田中 | 090-1234-5678, 080-2345-6789
2 | 鈴木 | 090-3456-7890
1NFの状態:
顧客ID | 名前 | 電話番号
-------|--------|--------------
1 | 田中 | 090-1234-5678
1 | 田中 | 080-2345-6789
2 | 鈴木 | 090-3456-7890
このように、各フィールドが単一の値を持つようにデータを整理します。
第二正規化(2NF)ってなに?
第二正規化(2NF)は、次の条件を満たす状態です:
- 1NFを満たしている: まず、テーブルが第一正規形(各フィールドが単一の値を持つようにデータを整理)であることが前提です。
- 部分的関数従属の排除: 複合主キーの一部にのみ依存する非キー属性がないこと。すべての非キー属性が主キー全体に完全に依存している必要があります。
例:
非正規化状態(部分的依存がある場合):
注文ID | 商品ID | 商品名 | 価格 | 注文数量
-------|--------|------------|-------
1 | 101 | ノート | 500 | 2
1 | 102 | ペン | 100 | 3
2NFの状態(商品情報を分離):
注文ID | 商品ID | 注文数量
-------|--------|-------
1 | 101 | 2
1 | 102 | 3
商品ID | 商品名 | 価格
-------|--------|-----
101 | ノート | 500
102 | ペン | 100
このように、商品に関する情報を別のテーブルに分け、重複や冗長性を減らします。これにより、データの一貫性が向上します。
複合主キーっていう、わざわざ複数の属性を主キーにしてるのに、その1つにしか関連づいていないデータがあったら、複合主キーの意味ないよねってなります。
っていうことで、1つにしか関連づいてない属性があるなら、それをメインとした新たなテーブル作っっちゃった方が整理されてていいよね!みたいな考え方が2NFです。
部分的関数従属をもっと砕いて表現すると?
部分的関数従属を理解するために、具体的な例を使って説明します。
例:
学校の生徒とクラスのテーブルを考えてみましょう。
・テーブル: 生徒(Student)/主キーは生徒IDとクラスIDを合わせた複合主キーの形式をとっている
生徒ID | 名前 | クラスID | クラス名 |
---|---|---|---|
1 | 山田 | 1 | 高校1年生A組 |
2 | 田中 | 2 | 高校1年生B組 |
3 | 鈴木 | 1 | 高校1年生A組 |
このテーブルは「生徒ID」と「クラスID」からなる複合主キーです。ここで「クラスID」は主キーの一部ですが、このテーブルの中で「クラス名」は「クラスID」だけで決まっています。
- 問題の発生: このテーブルにおいて、「クラスID」によって「クラス名」が決まりますが、同時に「生徒ID」にも依存しています。例えば、「生徒ID」が1の場合と3の場合は、どちらも「クラスID」が1であるため、同じ「クラス名」である「高校1年生A組」を持ちます。これによって、データの冗長性が生じ、更新時に整合性の問題が発生する可能性があります。
この問題を解決するために、第二正規形(2NF)では部分的関数従属を排除し、関連するデータを分割することでデータベースの設計を改善します。
第三正規化(3NF)ってなに?
第三正規化(3NF)は、次の条件を満たす状態です:
- 2NFを満たしている: テーブルが第一正規形にあり、かつ部分的関数従属を排除するため、非キー属性が候補キーのすべての属性に完全に依存することを保証します。
- 推移的関数従属の排除: 非キー属性が他の非キー属性に関数従属している場合、その関係を別のテーブルに移動します。つまり、非キー属性同士の関数従属がない状態を目指します。
例:
初期状態のテーブル
考えるテーブルは、顧客とその注文情報を含むものとします。
顧客と注文テーブル:
注文ID | 顧客ID | 顧客名 | 注文日 | 商品ID | 商品名 | 単価 | 注文数量 |
---|---|---|---|---|---|---|---|
101 | 1 | 山田 太郎 | 2024-06-01 | 1 | ノート | 500 | 2 |
101 | 1 | 山田 太郎 | 2024-06-01 | 2 | ペン | 100 | 3 |
102 | 2 | 田中 花子 | 2024-06-02 | 1 | ノート | 500 | 1 |
このテーブルは、第一正規形(1NF)と第二正規形(2NF)を満たしていますが、まだ第三正規形(3NF)ではありません。
第三正規形への変換
第三正規形では、非キー属性同士の関数従属を排除するため、テーブルを分割します。
1.顧客テーブル:
顧客ID | 顧客名 |
---|---|
1 | 山田 太郎 |
2 | 田中 花子 |
このテーブルでは、顧客IDが主キーとして機能し、顧客名がそれに関数従属しています。
2.注文テーブル:
注文ID | 顧客ID | 注文日 |
---|---|---|
101 | 1 | 2024-06-01 |
102 | 2 | 2024-06-02 |
このテーブルでも、注文IDが主キーとして機能し、顧客IDと注文日がそれに関数従属しています。
3.注文詳細テーブル:
注文ID | 商品ID | 単価 | 注文数量 |
---|---|---|---|
101 | 1 | 500 | 2 |
101 | 2 | 100 | 3 |
102 | 1 | 500 | 1 |
このテーブルでは、注文IDと商品IDの組み合わせが主キーとして機能し、単価と注文数量がそれに関数従属しています。
要するに…
テーブルを第三正規形に分割することで、各テーブルが単一のテーマに集中し、データの冗長性が減少します。また、データの整合性が保たれることで、データベースのパフォーマンスや保守性が向上します。
第三と第二の違いは?
正規化でよくでる疑問が、第二正規化と第三正規化の違いが分からないというものです。
第二正規形(2NF)と第三正規形(3NF)は、どちらも関数従属を排除することを目的としていますが、そのアプローチや対象とする関係性において異なる点があります。
ここでは、これら2つの違いを明確に区別できるようになりましょう!
第二正規形(2NF)
第二正規形では、主に複合キーに関する部分的関数従属を排除することを目的としています。具体的には、以下の特徴があります:
- 複合キーの使用: テーブルの主キーが複数の列から構成される場合、それぞれの非キー属性が主キー全体に関数従属していることを確認します。
- 部分的関数従属の排除: 複合キーの一部が他の非キー属性に関数従属している場合、それを別のテーブルに分割してデータの整合性を保ちます。
第三正規形(3NF)
第三正規形では、主に複合キーでない非キー属性同士の関数従属を排除することを目的としています。具体的には、以下の特徴があります:
- 非キー属性同士の関係: 複合キーでない非キー属性同士の関数従属が存在する場合、これを別のテーブルに分割します。
- 推移的関数従属の排除: 非キー属性が他の非キー属性に関数従属している場合、それを独立したテーブルに移動してデータの整合性を維持します。
主な違いとその影響
- 対象とする関係: 第二正規形は主に複合キーに対する部分的関数従属を解消しますが、第三正規形は非キー属性同士の関係に焦点を当てます。
- テーブルの分割基準: 第二正規形では、複合キーの一部分が他の非キー属性に関数従属しているかどうかを確認し、その場合に分割を行います。一方、第三正規形では、非キー属性同士の関数従属や推移的関数従属を見極めて、適切にテーブルを分割します。
- データの冗長性と整合性: 第三正規形への変換が進むほど、データの冗長性が少なくなり、データの整合性が強化されます。これは、より多くのテーブルを通じたデータの再利用性やパフォーマンスの向上に繋がります。
要するに、第二正規形は主に複合キーの構成に着目して部分的関数従属を排除し、第三正規形は非キー属性同士の関係性に焦点を当てて推移的関数従属を排除する点で異なります。これらの正規形は、データベース設計においてデータの整合性と効率性を確保するために重要な役割を果たします。
まとめ:第一~第三正規化までやってみよう!
データベースの正規化は、通常以下の流れに沿って行われます。ここでは第一正規形(1NF)、第二正規形(2NF)、第三正規形(3NF)までの流れを可視化して説明します。
第一正規形(1NF)
第一正規形に変換するためには、以下のルールを適用します:
- 単一の値: 各列(属性)は単一の値を持ちます。
- アトミックな値: 列内のデータはアトミックで、分解できないようにします。
例えば、以下の非正規化されたテーブルを考えてみます:
学生ID | 名前 | 電話番号 |
---|---|---|
1 | 山田太郎 | 123-4567-8901, 234-5678-9012 |
このテーブルは第一正規形を満たしていません。電話番号が複数の値を含んでおり、それを分解して以下のように第一正規形にします:
学生ID | 名前 | 電話番号 |
---|---|---|
1 | 山田太郎 | 123-4567-8901 |
1 | 山田太郎 | 234-5678-9012 |
これにより、各列が単一の値を持つ形に変換されました。
第二正規形(2NF)
第二正規形に変換するためには、以下のルールを適用します:
- 部分的関数従属の排除: 非キー属性が候補キー全体に依存するようにテーブルを分割します。
例えば、以下のテーブルを考えます:
注文ID | 顧客ID | 顧客名 | 注文日 | 商品ID | 商品名 | 単価 | 注文数量 |
---|---|---|---|---|---|---|---|
101 | 1 | 山田太郎 | 2024-06-01 | 1 | ノート | 500 | 2 |
101 | 1 | 山田太郎 | 2024-06-01 | 2 | ペン | 100 | 3 |
102 | 2 | 田中花子 | 2024-06-02 | 1 | ノート | 500 | 1 |
このテーブルでは「顧客ID」が「顧客名」に関数従属していますが、注文情報には直接関係がありません。この場合、以下のようにテーブルを分割します:
顧客テーブル:
顧客ID | 顧客名 |
---|---|
1 | 山田太郎 |
2 | 田中花子 |
注文テーブル:
注文ID | 顧客ID | 注文日 |
---|---|---|
101 | 1 | 2024-06-01 |
102 | 2 | 2024-06-02 |
注文詳細テーブル:
注文ID | 商品ID | 単価 | 注文数量 |
---|---|---|---|
101 | 1 | 500 | 2 |
101 | 2 | 100 | 3 |
102 | 1 | 500 | 1 |
これにより、非キー属性である「顧客名」が候補キーである「顧客ID」に完全に依存する関係を排除しました。
第三正規形(3NF)
第三正規形に変換するためには、以下のルールを適用します:
- 推移的関数従属の排除: 非キー属性が他の非キー属性に関数従属している場合、その関係を別のテーブルに移動します。
例えば、以下の注文詳細テーブルを考えます:
注文ID | 商品ID | 商品名 | 商品カテゴリ |
---|---|---|---|
101 | 1 | ノート | 文房具 |
101 | 2 | ペン | 文房具 |
102 | 1 | ノート | 文房具 |
このテーブルでは「商品名」と「商品カテゴリ」が「商品ID」に関数従属していますが、商品に関する情報は「商品ID」に依存すべきです。以下のように分割します:
商品テーブル:
商品ID | 商品名 | 商品カテゴリ |
---|---|---|
1 | ノート | 文房具 |
2 | ペン | 文房具 |
注文詳細テーブル:
注文ID | 商品ID | 単価 | 注文数量 |
---|---|---|---|
101 | 1 | 500 | 2 |
101 | 2 | 100 | 3 |
102 | 1 | 500 | 1 |
このようにして、非キー属性同士の関数従属を排除し、テーブルの分割を行うことでデータの整合性と効率が向上します。
おまけ:用語解説
非キー属性
非キー属性とは、テーブル内で主キー以外の属性(列)のことです。これらはレコードを一意に識別するためには使われず、他のデータを補完する情報を持っています。
部分的関数従属
部分的関数従属とは、複合主キーの一部にのみ依存している非キー属性が存在する状態を指します。これは、テーブル内で非キー属性が複合主キー全体ではなく、その一部だけに依存することを意味します。
要するに、複合主キーの中の、1つにしか関連(依存)していない属性があることを部分的関数従属といいます。で、1つにしか依存していないんだから、わざわざ複合主キーと関連付けるのではなく、その関連した1つを主キーとして、新たにテーブルを作った方がいいよねっていうのがNF2です。
複合主キー
複合主キーとは、データベースのテーブルにおいて、複数の列(属性)の組み合わせが一意であることを示す主キーのことです。
例えば、以下のようなテーブルを考えてみます:
- テーブル: 生徒クラス
生徒ID | クラスID | クラス名 |
---|---|---|
1 | 1 | 高校1年生A組 |
2 | 2 | 高校1年生B組 |
3 | 1 | 高校1年生A組 |
この場合、「生徒ID」と「クラスID」の組み合わせが主キーとなります。複合主キーでは、単一の列ではなく複数の列の組み合わせが必要となるため、それぞれの組み合わせが一意でなければなりません。
このように設定することで、例えば同じクラスに所属する生徒が複数いても、それぞれの生徒IDとクラスIDの組み合わせが異なるため、データベース内で一意性が保たれます。
候補キー
候補キー(Candidate Key)は、データベースのテーブル内で各行を一意に識別するための候補となる一連の属性(列)の組み合わせです。主キーを選ぶための候補として機能します。
具体的には、候補キーは以下の条件を満たします:
- 一意性: 候補キーの組み合わせは、テーブル内の各行を一意に識別できる必要があります。
- 最小性: 候補キーの組み合わせから1つでも属性を削除すると、一意性が保たれなくなるようなものです。
候補キーの中から、一般的に使用頻度が高く、また短く意味のあるものが主キーとして選ばれることがあります。
関数従属
関数従属(Functional Dependency)とは、ある属性(列)や属性の集合が別の属性に従属していることを意味します。具体的には、以下のような関係を示します:
- 単一属性の関数従属: ある属性 A が別の属性 B に完全に従属している場合、A が決まれば B も一意に決まる関係です。例えば、学生の学籍番号がわかれば、その学生の名前も一意に決まるという関数従属があります。
- 複数属性の関数従属: 複数の属性 {\(A_1, A_2, A_3, …. A_n\)}が別の属性 B に従属している場合、属性の組 {\(A_1, A_2, A_3, …. A_n\)} の値がわかれば B の値が一意に決まるという関数従属があります。例えば、顧客の住所と郵便番号の組み合わせがわかれば、その顧客の市区町村が一意に決まるという関数従属があります。
関数従属は、データベースの正規化において重要な概念であり、異なる正規形(1NF、2NF、3NFなど)を定義する基礎となります。正規化によって、データの冗長性を減らし、データの整合性を保つために、適切な関数従属の定義が行われます。
おわりに
本日はここまでです。今日は、DBにおける正規化(1NF,2NF,3NF)をStudy&マスターしてきました!ただカッコいいからという理由だけの方が、意外と集中して向き合うことができたのではないでしょうか?
そうなんです!「勉強しなきゃ!知識つけなきゃ!」のように勉強を義務にしてしまうと長く続きません。だからこそ、私たちは楽しんで知識を身に着けていきましょう!そんなことをやってるうちに気づいたらスペシャリストになっているかもしれません!
これからも、今日みたいに「the勉強するぞ!」という意気込みではなく、ヌルっと気づいたら知識が増えてた!みたいな軽い感覚でStudyを一緒にしていきましょう!
本日はここで、終わります。ありがとうございました。またお会いしましょう!では、さらばじゃ!