データベースの正規化

# データベースの正規化
データベースの正規化は、データの整合性を確保するために必要な手法です。正規化によって、データの重複を削除し、更新や削除に起因する問題を防止することができます。また、データのクエリに必要な情報を効率的に検索できるようになり、パフォーマンスも向上します。
正規化の目的は、データを分割し、それぞれのテーブルには唯一の目的があるようにすることです。この目的を達成するために、通常、以下のような一連の手順を実行します。

第1正規化：テーブルの各列には、一つの値しか入力されないようにします。つまり、複数の値が含まれる列は、別のテーブルに分割する必要があります。

第2正規化：テーブルの各列は、主キーに完全に依存する必要があります。主キー以外の列に重複したデータがある場合、それらを別のテーブルに分割する必要があります。

第3正規化：テーブルの各列は、主キーに直接にのみ依存する必要があります。つまり、非キー列によって他の列が決定されている場合、これらの列を別のテーブルに分割する必要があります。

それぞれの正規化の手順を実行することで、データベースを正規化することができます。ただし、過剰な正規化も問題を引き起こす可能性があります。例えば、テーブルを小さくしすぎると、クエリを実行するために複数のテーブルを結合する必要があり、それによってパフォーマンスが低下する可能性があります。
注意点としては、正規化はデータベースの設計段階で実行する必要があります。また、正規化は一つの手法であり、すべてのデータベースに対して適切な手法ではない場合もあります。正規化を実行する前に、データベースの要件を詳細に分析することが重要です。


# その他の手法

データベース設計において、正規化以外の手法としては、`デノーマライゼーション`、`反正規化`、`水平分割`、`垂直分割`などがあります。
デノーマライゼーションは、正規化の逆の操作であり、正規化を適用した後に、あえてデータの冗長性を増やすことで、クエリのパフォーマンスを向上させる手法です。ただし、データの冗長性を増やすことで、更新や削除の際に問題が生じる可能性があるため、適切に設計する必要があります。
反正規化は、正規化を適用する前に、データの冗長性を増やすことで、クエリのパフォーマンスを向上させる手法です。これは、大量の読み取り操作がある場合に有効で、更新や削除に関しては問題が生じる可能性があるため、注意が必要です。
水平分割は、テーブル内の行を複数のテーブルに分割することで、大量の行を含むテーブルのパフォーマンスを向上させる手法です。一方、垂直分割は、テーブル内の列を複数のテーブルに分割することで、列の数が多いテーブルのパフォーマンスを向上させる手法です。
これらの手法は、正規化と同様に、データベース設計において考慮すべき要素であり、データベースの要件に応じて適切な手法を選択することが重要です。


# それぞれの手法について、メリット・デメリット、採用基準例

## 【正規化】
### メリット：
* データの重複を排除し、データの整合性を保証することができる。
* データの更新や削除が容易になる。
* データの冗長性を低減することで、ストレージを節約することができる。
### デメリット：
* テーブルの数が増えるため、クエリのパフォーマンスが低下することがある。
* JOIN操作が頻繁に必要になるため、処理時間が長くなることがある。
* データの分割が過剰になると、冗長性が減りすぎてパフォーマンスが低下することがある。
### 採用基準：
* データの整合性が重要である場合。
* データの更新や削除が頻繁に行われる場合。
* ストレージ容量を節約したい場合。
## 【デノーマライゼーション】
### メリット：
* クエリのパフォーマンスが向上することがある。
* JOIN操作が減るため、処理時間が短縮されることがある。
### デメリット：
* データの冗長性が増えるため、更新や削除が困難になることがある。
* データの整合性が損なわれる可能性がある。
### 採用基準：
* 読み取り操作が頻繁に行われる場合。
* クエリのパフォーマンスが低下する場合。

## 【反正規化】
### メリット：
* クエリのパフォーマンスが向上することがある。
* JOIN操作が減るため、処理時間が短縮されることがある。
### デメリット：
* データの冗長性が増えるため、更新や削除が困難になることがある。
* データの整合性が損なわれる可能性がある。
### 採用基準：
* 読み取り操作が頻繁に行われる場合。
* クエリのパフォーマンスが低下する場合。
## 【水平分割】
メリット：
* テーブルの行数が減るため、クエリのパフォーマンスが向上することがある。
* データのセキュリティを向上させることができる。
* スケーラビリティが向上する。
### デメリット：
* テーブルの分割が過剰になると、JOIN操作が頻繁に必要になり、処理時間が長くなることがある。
* テーブル同士のリレーションシップを維持する必要があるため、設計が複雑になることがある。
### 採用基準：
* テーブルのサイズが大きく、読み取りや更新操作が頻繁に行われる場合。
* データのセキュリティが重要である場合。
* スケーラビリティを考慮する必要がある場合。
## 【垂直分割】
### メリット：
* テーブルの列数が減るため、クエリのパフォーマンスが向上することがある。
* データのアクセス制御が容易になることがある。
### デメリット：
* テーブルの分割が過剰になると、JOIN操作が頻繁に必要になり、処理時間が長くなることがある。
* テーブル同士のリレーションシップを維持する必要があるため、設計が複雑になることがある。
### 採用基準：
* テーブルの列数が多く、頻繁に使用される列とそうでない列がある場合。
* データのアクセス制御が重要である場合。

ただし、どの手法を採用するかは、データベースの設計目的や使用環境によって異なります。適切な手法を選択するためには、データベースの設計について深く理解し、慎重に判断する必要があります。

# それぞれの手法における使用例を具体的
## 【正規化】
例えば、以下のような社員情報を保持するテーブルがあるとします。
社員テーブル（社員番号、社員名、所属部署、年齢、役職）
このテーブルは、社員の情報を一元的に保持することができますが、部署ごとの情報を抽出するクエリを発行する場合、必要な情報が散在しているため、クエリのパフォーマンスが低下する可能性があります。そこで、以下のようにテーブルを正規化します。
社員テーブル（社員番号、社員名、年齢、役職）
部署テーブル（部署番号、部署名）
所属テーブル（社員番号、部署番号）
このようにテーブルを分割することで、部署ごとの情報を一括して取得するクエリが発行しやすくなります。
## 【デノーマライゼーション】
正規化されたテーブルを結合することによって、必要な情報を一度に取得することができますが、JOIN操作による処理時間が長くなる可能性があります。そこで、以下のようにテーブルをデノーマライズします。
社員テーブル（社員番号、社員名、年齢、役職、部署名）
このようにテーブルを結合することなく、必要な情報を一度に取得することができます。
## 【反正規化】
以下のような注文情報を保持するテーブルがあるとします。
注文テーブル（注文番号、注文日、顧客番号、顧客名、商品番号、商品名、数量、単価）
このテーブルは正規化されているため、顧客や商品の情報を保持するテーブルとJOIN操作を行う必要があります。しかし、このテーブルに対して頻繁にJOIN操作を行う場合、処理時間が長くなる可能性があります。そこで、以下のようにテーブルを反正規化します。
注文テーブル（注文番号、注文日、顧客番号、商品番号、数量、単価）
顧客テーブル（顧客番号、顧客名）
商品テーブル（商品番号、商品名）
このように、顧客や商品の情報を含めたテーブルを作成することで、JOIN操作を減少しでも軽減することができます。
## 【水平分割】
以下のような注文情報を保持するテーブルがあるとします。
注文テーブル（注文番号、注文日、顧客番号、商品番号、数量、単価）
このテーブルは、注文の情報を全て一つのテーブルに保持していますが、注文数が増えるとテーブルのサイズが大きくなり、パフォーマンスに影響を与える可能性があります。そこで、以下のようにテーブルを水平分割します。
注文テーブル1（注文番号、注文日、顧客番号、商品番号、数量、単価）
注文テーブル2（注文番号、注文日、顧客番号、商品番号、数量、単価）
このように、注文テーブルを複数のテーブルに分割することで、テーブルサイズを小さくすることができます。
## 【垂直分割】
以下のような顧客情報を保持するテーブルがあるとします。
顧客テーブル（顧客番号、顧客名、住所、電話番号、メールアドレス）
このテーブルは、顧客の全ての情報を一つのテーブルに保持していますが、顧客情報を取得する際に不要な情報が含まれている場合、パフォーマンスに影響を与える可能性があります。そこで、以下のようにテーブルを垂直分割します。
顧客テーブル1（顧客番号、顧客名、電話番号）
顧客テーブル2（顧客番号、住所、メールアドレス）
このように、顧客テーブルを複数のテーブルに分割することで、必要な情報だけを取得することができ、パフォーマンスを向上させることができます。