交差テーブルを作成する代わりにNULL入力可能な外部キーを使用することの欠点


15

次のERダイアグラムがあるとします。

ここに画像の説明を入力してください

ここSchoolStudent、inの外部キーを使用して関係を表す場合、NULL値を持つことができます(a Student に属する必要はないためSchool)。たとえば、

ここに画像の説明を入力してください

したがって、正しい方法(読んだ内容に基づいて)は、リレーションシップを表す交差テーブルを作成することです。次に例を示します。

ここに画像の説明を入力してください

この方法でNULLは、表に値を含めることはできませんSchool_has_Student

しかし、交差テーブルを作成する代わりにNULL入力可能外部キーを使用することの欠点は何ですか?


編集:

誤って(school_idstudent_id)をSchool_has_Studentテーブルのプライマリキーとして選択したため、多対多の関係になりました。正しい主キーは次のstudent_idとおりでした。

ここに画像の説明を入力してください


7
「正しい」方法はありません。ニーズに最適な方法があります。
メタファイト

1
私はDocに虚偽の前提について同意しますが、答えるのに十分なのはまだ明らかでしょうか?
メタファイト

誤った前提がありますが、違いをまっすぐに説明するのは簡単です。

近い投票を撤回しましたが、「読んだものに基づいた正しい方法は、関係を表す交差テーブルを作成することです」という文は、どのひずみソースがこれが「正しい」方法。以前読んだすべての教科書では、1:n関係の標準的な方法は単一の外部キーです。または、何かを誤解しましたか?
ドックブラウン

@Doc Brownどこで読んだか覚えていないが、交差テーブルが正しい方法であったと言っていることは確かだ。とにかく、1:nの関係(オプションで:1の側に参加)を単一の外部キーを使用して表す必要があるという本の名前を教えてもらえますか?
トム

回答:


18

2つのモデルは異なる関係を表します。

結合テーブルを使用することにより、多対多の関係をモデル化しています。

単純な外部キーを使用することにより、1対多の関係をモデル化しています。

ヌル可能外部キーの欠点は、それを達成しようとしている場合、多対多として関係をモデル化できないことです。


質問の編集に基づいて、学生キーを同じキーを持つ2つのテーブルに効果的に分割します。私は通常、あまりにも多くのフィールドを持つテーブルでこれを見るので、誰かがそれらを2つに分割して管理しやすくします(豚に口紅をつけると呼びます)。

学生テーブルを分割することにより、2番目のテーブルにレコードが存在する必要がないため、2番目のテーブルをオプションにします。これは、nullになる可能性があるため、設定する必要のないフィールドに非常に似ています。

1対多の関係が必要な場合は、単一のテーブルを使用して、学生テーブルで学校IDをnullにすることをお勧めします。外部キーであっても、フィールドのnullを回避する理由はありません。これは、外部関係がオプションであることを意味します。開発者とDBAはそのことを明確に理解しており、基盤となるデータベースエンジンは確実に正常に動作するはずです。

結合について心配している場合は、心配しないでください。結合がNULLフィールドとどのように機能するかについては、明確に定義されたセマンティクスがあります。単一のテーブルを使用すると、3つではなく2つのテーブルを結合できます。


したがって、1対多の関係をモデル化する場合(オプションで:1側に参加する場合)、NULL値を持つことができるという事実にもかかわらず、外部キーを使用する必要がありますか?
トム

1
@Tomはい、それはまさにそれをモデル化する方法です。結合テーブルを使用することは技術的に可能ですが、データモデルでは多対多が許可されるため、トリガーとデータベースロジックを使用してそれを防ぐ必要があります。誤ったデータを追加できないように関係を制限することで、より良い結果が得られます。

1
私は自分の質問を編集しました。テーブルstudent_idでは主キーのみを作成し、1 School_has_Student対多の関係を維持しました。この方法には、外部キーの使用に比べてどのような欠点がありますか?
トム

@Tom答えを編集しました。

7

上記のコメントに書いた:

「データベースシステムの基礎」という本[...]には[...]と書かれていますが、外部キー列に多くのNULL値がある場合(たとえば:従業員の98%部門を管理しないでください)

外部キー列に多くのNULL値がある場合、プログラムは処理するレコードごとにこのほとんど空の列を処理する必要があります。すべてのケースの98%が空であるにもかかわらず、列はおそらくディスクスペースを占有します。関係のクエリとは、より多くのネットワークトラフィックを提供する列をクエリすることを意味し、テーブルからクラスを生成するORMを使用している場合、プログラムまた、クライアント側に必要以上のスペースが必要です。交差テーブルを使用すると、これを回避できます。そうしないと、同等の外部キーがNULLにならない場合に必要なリンクレコードのみが存在します。

それとは反対に、NULL値が少数ではない場合、50%以上のリレーションがNULLでないとすると、交差テーブルを使用すると逆の効果が得られます-より多くのディスクスペース、より複雑なネットワークトラフィックなど。

そのため、交差テーブルの使用は最適化の一形態にすぎず、特定の場合にのみ意味があります。特に最近では、ディスク容量とメモリが安くなり、必要性がはるかに低くなりました。「データベースシステムの基礎」は、もともと20年以上前に書かれていることに注意してください(1994年からの第2版への参照を見つけました)。1994年以前は、大容量記憶装置は依然として高価であり、コンピューターとネットワークは今日よりもずっと低速だったため、スペースの最適化はおそらく今日よりもはるかに重要でした。

慎重なコメントへの補足として:上記のステートメントは、「データベースシステムの基礎」の著者が彼の勧告で念頭に置いていたものを予想しようとしているだけであり、ほとんどのシステムに有効な大まかな一般的なステートメントを作成していると思います。一部のデータベースには、交差テーブルの使用をさらに時代遅れにする「スパース列」のような他の可能な最適化があります。

したがって、その推奨事項を間違って取得しないでください。この本は{0,1}:n、一般的なリレーションシップのために交差テーブルを好むように、または、あなたが書いたように、これが「正しい方法」であることをあなたに教えません。このような最適化を使用すると、本当に必要な場合にのみプログラムが複雑になります。


特にOPが特定のものを言及していないことを考慮すると、データベースの実装について多くのことを想定しています。データベースは、スパース列に少量のスペースしか使用できないほどスマートです。
ガーデンヘッド

@gardenhead:これが「可能性が高い」と信じる理由は何ですか?
ドックブラウン

データベースは数十年前から存在しており、ほとんどのインフラストラクチャの重要なコンポーネントであるため、高度に最適化されています。
ガーデンヘッド

@gardenhead:あなたは私よりも多くの不当な仮定をしているように聞こえます。それにもかかわらず、私の編集を参照してください。
ドックブラウン

2

概念モデルはある、このようになります。非常に異例の少ない言うこと:

ここに画像の説明を入力してください

物理モデルは次のようになりますが、これは控えめに言っても混乱します(よく見ると、人々はM:Mだと思うでしょう):

ここに画像の説明を入力してください

私のおすすめ:

必要に応じて、ほとんどの学生に適用されない多くの列(FKまたはその他)を、1対1の関係でロールテーブルに分割します。しかし、それはそれらがFKであるためではなく、列がほとんどの行に適用されないためです。

それ以外の場合null許容FKはデータベースの通常の部分であり、結合テーブルは通常M:M rel用です。

1:1 relの一般的な用途は、エンティティが特定のタイプである場合にのみ適用される列を持つロールテーブルと、パフォーマンスまたはストレージを考慮してBLOB列を抽出することです。FKでnull値を避けることは、そのための一般的な使用法の1つではありません。

ここに画像の説明を入力してください


2

他の回答に加えて、外部キーのnull値があいまいであることを指摘したいと思います。それはどういう意味ですか:

1)生徒の学校(ある場合)が不明です(これは 'null'の標準的な意味です-値は不明です)

2)生徒が学校を持っているかどうかがわかっており、学校がない

nullの標準的な意味を使用する場合、外部キーモデルで「生徒には学校がない」をどのように表現しますか。その場合、おそらく学校のテーブルに独自のIDを持つ「学校なし」のエントリを作成する必要があります。(理想的ではない)


2
「データベースシステムの基礎」という本は、には3つの解釈があると述べていますNULL。1)不明な値。2)利用できない値または差し控えられた値。3)該当しない属性(この解釈はNULL、外部キーにを指定できることを意味すると思います)。
トム

1
これは便利なリストですが、null(または実際に任意の値)のセマンティクスはユーザー定義可能です。すなわち、それはデザイナーがそれが意味することを意味することができ、そのリストに限定されません。問題は1つが必要な(あるいは意図せずに保存)するかもしれないより多くの時に異なる意味を区別する方法です
ブラッド・トーマス・

それで、null許容の外部キーを使用する代わりに、交差テーブルを作成することを提案していますか?
トム

@Tomはい、私はこの場合の方が良いと信じています
ブラッドトーマス

@BradThomas-交差テーブルを使用するときに同じ曖昧さを避けるために、NULLのSchool_IDを持つ交差テーブルのレコードでケース2(生徒に学校がないことがわかっている)を表しますか?
アンドリュー

1

データベーステーブルには、制約と呼ばれるこの素晴らしい機能があります。そのため、各生徒の1人だけがテーブルに表示できる交差テーブルで作成するのは非常に簡単ですが、そのテーブルには多くの学校があります。効果的にあなたに与える

理論は優れていますが、最終的には、質問をした後にデータベースをモデル化することになります。

「どの生徒が私の学校にいるのか」という質問で頻繁に質問したい場合は、本当に生徒テーブル全体を照会するか、簡単な交差テーブルを作成しますか。

データベースの場合:質問に合わせて最適化します。


0

3番目のテーブルを使用すると実際に意味があるユースケースがあります。この例は純粋に仮想的なもののように思えるかもしれませんが、それが私のポイントをうまく示していることを願っています。studentsテーブルにさらに列を追加し、ある時点で、複数の列の複合インデックスを介してレコードに一意性を適用することにしたとします。school_id列も含める必要がある可能性が非常に高く、ここからは混乱が始まります。SQLの設計方法により、可能な場合school_idは複数の同一のレコードを挿入しNULLます。技術的な観点からは完全に理にかなっていますが、直感に反し、予期しない結果を招く可能性があります。一方、交差テーブルで一意性を強制することは簡単です。

最近、一意性制約の要件がタイムスタンプ列によるものである、このような「オプション」関係をモデル化する必要がありました。ヌル可能外部キーをテーブルに残しておくと、突然同じタイムスタンプを持つレコードを挿入する可能性につながります(まだ監査/承認されていないレコードに設定されたデフォルトのレコードであると仮定しましょう)-唯一の解決策は削除することでしたヌル可能列。

ご覧のとおり、これはかなり特殊なケースであり、他の人が指摘したように、ほとんどの場合、すべてのNULL値で完全に大丈夫です。モデルの特定の要件に本当に依存します。


0

すでに提出された多くの良い提案に加えて、個人的には、本当に必要でない限り、外部キーのファンではありません。最初に、参照しているM:M関係があります。さらに、外部キーを呼び出して、そのテーブルデータをクエリに取り込むと、より複雑になり、テーブルサイズによってはパフォーマンスが低下します。他の人が言ったように、ヌル可能FKフィールドはサポートされていない可能性があり、データの整合性の問題を引き起こす可能性があります。

学生の学校が不明または空の状態を定義している場合、NULLはこれらの条件を区別しません。(再度、データの整合性に戻ります。)Tulainsによるロールテーブルの提案はエレガントで、null値をきれいに許可します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.