データベースにおける正規化
データベースのコンテキストにおける正規化とは、リレーショナルデータベースの構造を設計するプロセスであり、データの冗長性を削減し、データの整合性を向上させることを目的としています。正規化の主な目標は次のとおりです。
-
データの冗長性の排除
正規化は、各データ要素が一箇所にのみ保存されることを保証します。これはデータベースを論理的にテーブルに分割し、それらの間に関係を確立することによって達成されます。 -
データ変更の問題の最小化
データが複数の場所に保存されている場合、変更時の一貫性の維持は困難になります。正規化により、各データが一箇所に存在することが保証されるため、データの変更がより管理しやすくなります。 -
クエリの簡素化
正規化されたデータベース内の整理された非冗長なデータは、クエリの実行を容易にします。これにより、特に大規模なデータベースの場合にパフォーマンスが向上します。 -
データの整合性の維持
正規化は、冗長性を削減し、テーブル間に明確な関係を確立することにより、データの正確性と一貫性を維持するのに役立ちます。 -
将来のデータへの対応
適切に正規化されたデータベースは、将来の変更に対して柔軟に対応できます。業務要件が進化するにつれて、よく正規化された場合はデータベースの変更が容易になります。
正規形
正規化では、正規形と呼ばれる一連のルールがデータの冗長性を削減し、論理的な整合性を向上させます。第一正規形(1NF)から第五正規形(5NF)までの進展には、ますます厳格なルールが含まれています。
第一正規形(1NF)
テーブルが第一正規形にあるとは、次の条件を満たしていることを意味します。
- 主キーが存在する
- 全ての属性が原子的な値(さらに分解できない値)を含んでいる
- 列内のエントリは同じ種類のもの
例
学生を記録するテーブルを考えてみます。
Student_ID | Name | Courses |
---|---|---|
1 | Alice | Math, History |
2 | Bob | Science |
3 | Carol | Math, Science, History |
このテーブルは1NFにはなっていません。なぜなら、Courses
列には非原子的な値が含まれているからです。これを1NFに準拠するために、データを別々の行に分割することができます。
Student_ID | Name | Course |
---|---|---|
1 | Alice | Math |
1 | Alice | History |
2 | Bob | Science |
3 | Carol | Math |
3 | Carol | Science |
3 | Carol | History |
第二正規形(2NF)
テーブルが第二正規形にあるとは、次の条件を満たしていることを意味します。
- 第一正規形になっている
- 部分的な依存関係が存在しない(つまり、非主属性がいかなる候補キーの真部分集合にも依存していない)
例
学校で異なる教室に学生が割り当てられるテーブルを考えてみます。
Student_ID | Class_ID | Class_Room | Subject |
---|---|---|---|
1 | A | 101 | Math |
2 | B | 102 | Science |
ここで、Student_ID
とClass_ID
の組み合わせが主キーとなります。Class_Room
は主キーの一部であるClass_ID
にのみ依存しているため、部分的な依存関係があります。このテーブルを2NFにするために、次のように2つのテーブルに分割することができます。
- 学生テーブル
Student_ID | Class_ID | Subject |
---|---|---|
1 | A | Math |
2 | B | Science |
- クラステーブル
Class_ID | Class_Room |
---|---|
A | 101 |
B | 102 |
第三正規形(3NF)
テーブルが第三正規形にあるとは、次の条件を満たしていることを意味します。
- 第二正規形になっている
- 推移的な依存関係が存在しない(つまり、非主属性が他の非主属性に依存していない)
例
さまざまな通貨での商品と価格を記録するテーブルを考えてみます。
Item_ID | Item_Name | Currency | Exchange_Rate | Price_in_USD |
---|---|---|---|---|
1 | Book | EUR | 1.2 | 20 |
2 | Pen | EUR | 1.2 | 2 |
ここで、Price_in_USD
は主キーではないExchange_Rate
に依存しています。これは推移的な依存関係です。このテーブルを3NFにするために、次のように2つのテーブルに分割することができます。
- 商品テーブル
Item_ID | Item_Name | Currency | Price_in_USD |
---|---|---|---|
1 | Book | EUR | 20 |
2 | Pen | EUR | 2 |
- 通貨テーブル
Currency | Exchange_Rate |
---|---|
EUR | 1.2 |
第四正規形(4NF)
テーブルが第四正規形にあるとは、次の条件を満たしていることを意味します。
- 第三正規形になっている
- 多値の依存関係が存在しない(属性が他の属性に依存しているが、キーには依存していない)
例
異なる部署の従業員のスキルを記録するテーブルを考えてみます。
Employee_ID | Department | Skill |
---|---|---|
1 | HR | Writing |
1 | HR | Speaking |
2 | IT | Coding |
2 | IT | Testing |
ここで、Skill
はDepartment
には依存していますが、両方がEmployee_ID
に依存しています。これは多値の依存関係です。このテーブルを4NFにするために、次のように2つのテーブルに分割することができます。
- 従業員テーブル
Employee_ID | Department |
---|---|
1 | HR |
2 | IT |
- スキルテーブル
Employee_ID | Skill |
---|---|
1 | Writing |
1 | Speaking |
2 | Coding |
2 | Testing |
第五正規形(5NF)
テーブルが第五正規形またはプロジェクト・ジョイン正規形にあるとは、次の条件を満たしていることを意味します。
- 第四正規形になっている
- データを失うことなく、または誤ったデータを生成することなく、より小さなテーブルに分解することができない
この正規形は、複数の小さなテーブルを結合することで元のテーブルを再構築できる場合に関連します。ほとんどの実用的な目的では、第四正規形までで十分であり、第五正規形はより複雑または特殊なシナリオで使用されます。
非正規化
非正規化は、正規化されたデータベースに戦略的に冗長性を組み込み、読み取りパフォーマンスを最適化するプロセスです。正規化はデータの整合性を維持し異常を回避するために不可欠ですが、クエリにおける複数のテーブルの結合の必要性によりパフォーマンスの問題が生じる場合があります。このような場合に非正規化が役立つ状況がいくつかあります。
-
読み取りが主体のワークロード
データベースが主に読み取り操作に使用され、クエリのパフォーマンスが重要な場合、非正規化によりテーブルの結合の必要性が減り、クエリが高速化されます。 -
レポートと分析
データベースがレポートや分析に使用される場合、非正規化によりデータが複雑なクエリや集計に適した形式で構造化されます。 -
アプリケーションのデータ検索の簡素化
非正規化により、クライアントアプリケーションにおけるデータの検索がより簡単になり、SQLクエリの複雑さが減ります。 -
スケーリングとリソースの制約
リソースが限られている状況では、非正規化を使用してパフォーマンスを向上させることがあります。これにより、より強力なハードウェアに頼らずにパフォーマンスを向上させることができます。
正規化と非正規化のバランス
非正規化は全てか無しのアプローチではありません。多くの場合、最良のデータベース設計は正規化と非正規化のバランスが求められます。これをハイブリッドアプローチと呼びます。ハイブリッドアプローチでは、データの整合性を維持するために一部のデータベースを正規化し、読み取りパフォーマンスを最適化するために他の部分を非正規化します。非正規化の場所を決定する際には、アプリケーションやシステムの具体的な要件と制約を慎重に考慮する必要があります。