さて、私が理解しているように、データの正規化の背後にある一般的な原則は、データの冗長性が最小限に抑えられたRDBMSを作成することです。
うーん、わかりました。
私のプロジェクトでは、DB担当者の1人がDBを作成しました。50以上のテーブルがあり、DB内のテーブルは通常、非常に断片化されています。テーブルには2つまたは3つの列があり、それだけです。
テーブルの数は、デザインが良いか悪いかについては何も言いません。一部の企業は1つまたは2つを必要とします。他の人はもっと必要です。私は何千ものテーブルを持つフォーチュン500のデータベースに取り組んできました。
列の数は、デザインが良いか悪いかについては何も言いません。また、列の数は断片化とは関係ありません。列が比較的少ないテーブルは、一般的に良い兆候だと思います。必ずしも良い兆候ではありませんが、一般的には良い兆候です。
さて、SQLクエリを書くことになると、各クエリはいくつかの異なるテーブルをくまなく調べてそれらを結合する必要があるため、それはちょっとした面倒になりました。これはデータの正規化の副作用なのだろうか?それとも、これは何か他のものを指しているのでしょうか?
それには2つの異なる一般的な理由があります。
テーブルを正規化する場合、機能の依存関係を識別し、1つ以上の新しいテーブルで機能に依存する列を分離し、元のテーブルから削除することで、冗長性を減らします(データの整合性を高めます)。したがって、より低い正規形からより高い正規形に移動するという意味で、テーブルを正規化します。
- 常にテーブルの数を増やし、
- 常に元のテーブルの列数を減らし、
- 人間のデータを取得するために結合が必要になる場合があります。
もう1つの一般的な方法は、文字列をID番号に置き換えることです。これは正規化とは何の関係もありません。(「ID番号の正規形」などはありません。)文字列をID番号に置き換える
- 常にテーブルの数を増やし、
- 元のテーブルの列数は変更されません(正規化と同時に行われない限り)。
- 人間のデータを取得するには、常に結合が必要です。
このスレッドの他の部分には混乱があるようです。厳密に言えば、次のいずれもOPの質問に直接関係していないことを理解しています。
1NFは「1つの価値」の原則です。行が「アトミック」であることとは何の関係もありません。リレーショナルモデルでは、アトミックは行を参照しません。値を参照します。
「1つの値」とは、行と列の各交差に1つの値が含まれることを意味します。(言い換えると、値は「アトミック」です。しかし、アトミックという言葉にはいくつかの不幸な意味があるため、ほとんどの現代の実務家はそれを避けています。)その値は単純である必要はありません。任意に複雑にすることができます。ただし、それ自体に意味のある部分がある場合、dbmsはそれらの部分を完全に無視するか、それらを操作する関数を提供します。(パーツを操作するための関数を作成する必要はありません。)
最も簡単な例は日付だと思います。日付には、年、月、日で構成される部分があります。dbmsは、これらの部分を無視するか(のようにSELECT CURRENT_DATE
)、それらを操作する関数を提供します(のようにSELECT EXTRACT(YEAR FROM CURRENT_DATE)
)。
「1つの価値」の原則をかわそうとする試みは、当然の結果、「繰り返しグループなし」の原則につながります。
繰り返しグループには、1つのドメインからの複数の値が含まれ、すべての値が同じ意味を持ちます。したがって、次のような表は、ある種の繰り返しグループの例です。(他の種類もあります。)「phone_1」と「phone_2」の両方の値は同じドメインからのものであり、同じ意味を持ちます。ユーザー「n」には電話番号(phone_1とphone_2)があります。(主キーは「user_id」です。)
user_id phone_1 phone_2
1 (111) 222-3333 (111) 222-3334
2 (111) 222-3335 (111) 222-3336
しかし、次の表は非常に似ていますが、繰り返しグループがありません。値は同じドメインからのものですが、同じ意味を持っていません。(主キーは「user_id」です。)
user_id home_phone work_phone
3 (111) 222-3333 (111) 222-3334
4 (111) 222-3335 (111) 222-3336
2NFは「全体の鍵」の原則です。キーの数とは何の関係もありません。'n'列を持つテーブルは'n'キーを持つことができます。(たとえば、この他のSOの回答を参照してください。)リレーショナルモデル(および、拡張として、正規化の演習を行う場合)で、keyという単語が単独で表示される場合は、「候補キー」と考えてください。
代わりに、2NFは複数の列を持つ候補キーと関係があります。候補キーに複数の列がある場合、2NFでは、すべての非プライム属性が、候補キーの一部の列だけでなく、すべての候補キーのすべての列に機能的に依存している必要があります。(非プライム属性は、候補キーの一部ではない属性です。)
次の例は、2nfのウィキペディアのエントリを基にしています。(主キーは{従業員、スキル}です。)
Table: employee_skills
employee skill current_work_location
--
Jones Typing 114 Main Street
Jones Shorthand 114 Main Street
Jones Whittling 114 Main Street
Bravo Light Cleaning 73 Industrial Way
Ellis Alchemy 73 Industrial Way
Ellis Flying 73 Industrial Way
Harrison Light Cleaning 73 Industrial Way
非プライム列current_work_locationが主キー{employee、skill}に機能的に依存していることは事実ですが、主キー「employee」の一部にのみ機能的に依存しています。そのテーブルは2NFにはありません。
各行に代理キーを割り当てて、2NFの問題を回避することはできません。(主キーはes_idです。以前の主キー{employee、skill}にはUNIQUE制約があります)。
Table: employee_skills
es_id employee skill current_work_location
--
1 Jones Typing 114 Main Street
2 Jones Shorthand 114 Main Street
3 Jones Whittling 114 Main Street
4 Bravo Light Cleaning 73 Industrial Way
5 Ellis Alchemy 73 Industrial Way
6 Ellis Flying 73 Industrial Way
7 Harrison Light Cleaning 73 Industrial Way
ID番号を追加しても、部分的な依存関係は削除されないことは明らかですemployee->current_work_location
。部分的な依存関係を削除しない限り、このテーブルはまだ2NFにありません。
3NFは、「推移的な依存関係なし」の原則です。ここで採用されているウィキペディアの例からわかるように、派生データや計算データとは必ずしも関係ありません。(主キーは{トーナメント、年}です。このテーブルは3NFではありません。)
Table: tournament_winners
tournament year winner winner_date_of_birth
--
Indiana Invitational 1998 Al Fredrickson 21 July 1975
Cleveland Open 1999 Bob Albertson 28 September 1968
Des Moines Masters 1999 Al Fredrickson 21 July 1975
Indiana Invitational 1999 Chip Masterson 14 March 1977
2つの依存関係は、このテーブルに推移的な依存関係があることを示しています。
- winer_date_of_birthの値は、機能的に主キーに依存しているように見えます。各主キー値は、winner_date_of_birthの唯一の値を決定します。だが 。。。
- winer_date_of_birthの値も、機能的に勝者に依存しているように見えます。勝者の各値は、winner_date_of_birthの唯一の値を決定します。
これらの2つの明らかな機能依存性と、トーナメント、勝者、および生年月日という言葉の意味の理解を考えると、次のように言うことができます。
- 勝者->winner_date_of_birthは機能依存性であり、
- {トーナメント、年}->勝者は機能従属性であり、
- {トーナメント、年}->winner_date_of_birthは推移的な依存関係です。