SQL-多対多テーブルの主キー


125

この質問は、この質問のコメントを読んだ後に出てきます。

データベース設計

多対多のテーブルを作成する場合、2つの外部キー列に複合主キーを作成するか、自動インクリメントサロゲート "ID"主キーを作成し、2つのFK列(およびおそらく一意の制約)?いずれの場合も、新しいレコードの挿入/再インデックス付けのパフォーマンスにどのような影響がありますか?

基本的に、これ:

PartDevice
----------
PartID (PK/FK)
DeviceID (PK/FK)

対これ:

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)

コメンターは言う:

2つのIDをPKにすることは、テーブルがディスク上で物理的にその順序でソートされることを意味します。したがって、(Part1 / Device1)、(Part1 / Device2)、(Part2 / Device3)を挿入すると、(Part 1 / Device3)データベースはテーブルを分割し、最後のテーブルをエントリ2と3の間に挿入する必要があります。多くのレコードでは、レコードが追加されるたびに数百、数千、または数百万のレコードをシャッフルする必要があるため、これは非常に問題になります。対照的に、自動インクリメントPKを使用すると、新しいレコードを最後まで追加できます。

私が質問している理由は、代理の自動インクリメント列がない複合主キーを常に実行する傾向があるためですが、代理キーの方が実際にパフォーマンスが高いかどうかはわかりません。


:ここではSOに掲載silimar質問だstackoverflow.com/questions/344068/...
トニー・

(これを以前のコメントに追加しようとしましたが、できません)挿入の数によっては、定期的にインデックスを再構築して、結果が迅速に返されるようにすることもできます。SQL Serverでは、インデックスのFILLFACTORを調整して、データを移動する前に挿入のための十分なスペースを提供することもできます。
Tony

1
これに対する答えは、使用されているDBMSに依存しませんか?私は、MySQLが少しなど別の方法でこの場合、SQL-Serverのように動作します疑う
ラドゥMurzea

警告:特定のデータベースタグがなければ、ここでの発言の多くは疑わしいものです。エンジンによって動作は異なります!
リックジェームス

回答:


85

単純な2列の多対多マッピングでは、代理キーを使用することには本当に利点はありません。主キーをオンにすること(col1,col2)は一意であることが保証され(参照されるテーブルのcol1col2値が一意であると仮定)、別のインデックスをオンに(col2,col1)すると、反対の順序で実行が速くなるケースがキャッチされます。サロゲートはスペースの無駄です。

テーブルは、2つの参照テーブルを結合するためにのみ使用する必要があるため、個々の列にインデックスは必要ありません。

私の意見では、あなたが質問で参照するコメントは、使用する電子の価値はありません。作成者は、テーブルが非常に高いパフォーマンスのバランスのとれた多方向ツリー構造ではなく、配列に格納されていると考えているようです。

まず、ソートされたテーブルを格納または取得する必要はなく、インデックスのみです。また、インデックスは順番に保存されるのではなく、効率的に保存され、すばやく取得できます。

さらに、データベーステーブルの大部分は、書き込まれるよりもはるかに頻繁に読み取られます。これにより、選択側で行うことは、挿入側で行うことよりもはるかに関連性が高くなります。


最後のポイントは適切な一般化ではありません。「データベーステーブルの大部分は、書き込まれるよりもはるかに頻繁に読み取られます」。顧客を注文にリンクするテーブルなど、頻繁に書き込む必要がある連想テーブルの多くの例を見つけました。
ユーザー

5
@buffer、私はそのコメントを待機します(技術的には、「すべてのテーブル」、「大多数のバスト」は経験に基づいている場合にのみ一般化されます)。例についても考えてみましょう。注文は1回作成されます(時々更新される可能性がありますが、注文のステータスなどにヒットするためにキー/インデックス情報が変更されることはほとんどありません。ただし、これらの更新と選択する必要がある選択)請求書を印刷したり、管理レポートを生成したりすると、元の挿入物を上回ります
paxdiablo 2013

アマゾンを考える-毎時間数千の注文が作成されます。
ユーザー

9
@バッファ、はい、しかし、繰り返しになりますが、これらの各注文は、ほぼ確実に、(たとえば)パッケージ化、請求、ステータスの更新、ビジネス分析などを行うために何度も照会されます。作成の絶対数は、作成と読み取りの比率ほど重要ではありません。
paxdiablo 2013

1
私のポイントは、insertそれが1時間に数千回行われる場合に重要になります。割合という理由だけであなたは、単にそれを無視することはできませんinsertにはselect、<この場合は1である、それは順序を置くためにかかる時間について、顧客の心配事を。
ユーザー

19

リンクテーブルに代理キーは必要ありません。

(col1、col2)の1つのPKと(col2、col1)の別の一意のインデックスで十分です

対処できず、DB設計を指示するORMを使用しない限り...

編集:私はここで同じように答えました:SQL:多対多テーブルの自動インクリメンタル主キーが必要ですか?


3
(col2、col1)の一意のインデックスではなく、col2の重複インデックスで問題ない場合があります。2列インデックスの利点は、col2のみ、またはcol1とcol2の両方でインデックスのみのスキャンが可能になることです(ただし、(col1、col2)のもう一方のインデックスも「両方」のケースを処理します)。欠点は、追加のカラムに必要な追加のストレージです。これは通常重要ではないので、アドバイスはひどいものからはほど遠いです。それでも、col1とcol2が大きいか、サイズが大きく異なる場合は、短い列に2番目のインデックスを配置することを選択することで、パフォーマンスを低下させることなくスペースを節約できます。
ジョナサンレフラー、

@gbn:(col2、col1)の2番目のインデックスは一意である必要はありませんよね?
ユーザー

1
(col1、col2)に一意のインデックスを付けることは、それが既にPKである場合、完全に冗長です
Don Cheadle、

@mmcrae:どこでやってるの?
gbn 2014年

2
@mmcrae:あなたのコメントは「(col1、col2)..に一意のインデックスを付ける」です。インデックスの列の順序は重要です。(col2, col1)はありません(col1, col2)。のPKは(col1, col2)すべてのクエリに適していない場合があり、スキャンを生成します。その逆を使用すると、col2の方が良い場所でのシークが可能になるため、パフォーマンスが向上します。たとえば、col2を持つテーブルに削除がある場合のFK検証。子テーブルの
スマットを

12

テーブルが参照されている場合、増分主キーが必要になる可能性があります。インクリメンタル主キーを使用して別のテーブルからプルアップする必要がある多対多のテーブルに詳細がある場合があります。

例えば

PartDevice
----------
ID (PK/auto-increment)
PartID (FK)
DeviceID (FK)
Other Details

FKとしてPartDevice.IDを使用すると、「その他の詳細」を簡単にプルできます。したがって、増分主キーの使用が必要です。


1
ありがとう!あなたが説明したのとほとんど同じシナリオを探していたので、私は答えに行きました。しかし、「その他の詳細」を追加することにより、最初の文から離れました。多対多のマッピングテーブルがあり、別のテーブルから参照する必要がある場合はどうなりますか?つまり、多対多マッピングテーブルには他の情報は保存されていません...とにかく追加のID列は意味がありますか?そうでない場合は、代わりにマッピングテーブルの1つのレコードを参照する方法を教えてください。
misanthrop

ここには2つのオプションがあります。複合キーを参照テーブルの外部キーとして使用する(これにより、新しいテーブルに列が追加されます)か、マッピングテーブルにid列を作成して、元の複合に一意の制約を設定できます。新しいid列が主キーになります。
Vočko

6

私があなたの質問に答えることができる最も短くて最も直接的な方法は、リンクしている2つのテーブルに順次主キーがない場合、パフォーマンスに影響があるということです。あなたが述べたり引用したりしたように、リンクテーブルのインデックスが断片化するか、リンクテーブルに独自の順次主キーがない場合、DBMSはレコードを挿入するためにより困難に動作します。これが、ほとんどの人がリンクテーブルに順次インクリメントする主キーを配置する理由です。


2

したがって、2つのテーブルをリンクすることが唯一の仕事である場合、最適なPKはデュアルカラムPKになるでしょう。

ただし、他の目的に役立つ場合は、別のNDXを外部キーと2番目の一意のインデックスを持つPKとして追加します。

インデックスまたはPKは、重複がないことを確認するための最良の方法です。PKを使用すると、Microsoft Management Studioなどのツールで一部の作業(ビューの作成)を実行できます

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