14

私のデータベースには、多対多の関係を持つ次のテーブルがあります。これは、各メイン テーブルの主キーへの外部キーを持つ接続テーブルによって表されます。

  • ウィジェット: WidgetID (PK)、タイトル、価格
  • ユーザー: UserID (PK)、FirstName、LastName

各ユーザー ウィジェットの組み合わせは一意であると想定します。データ関係を定義する接続テーブルを構築する方法について、次の 2 つのオプションがあります。

  1. UserWidgets1: UserWidgetID (PK)、WidgetID (FK)、UserID (FK)
  2. UserWidgets2: WidgetID (PK、FK)、UserID (PK、FK)

オプション 1 には、主キーの列が 1 つあります。ただし、テーブルに格納される唯一のデータは 2 つのプライマリ テーブル間のリレーションシップであり、このリレーションシップ自体が一意のキーを形成できるため、これは不要に思えます。したがって、2 列の主キーを持つオプション 2 につながりますが、オプション 1 が持つ 1 列の一意の識別子が失われます。オプションで、2 列の一意のインデックス (WidgetID、UserID) を最初のテーブルに追加することもできます。

UserWidgets の多対多テーブルを構築するために、パフォーマンスに関して 2 つの実際の違い、または一方のアプローチを他方より優先する理由はありますか?

4

9 に答える 9

24

いずれの場合も、主キーは 1 つしかありません。2 つ目は複合キーと呼ばれるものです。新しいコラムを導入する正当な理由はありません。実際には、すべての候補キーに一意のインデックスを保持する必要があります。新しい列を追加しても、メンテナンス オーバーヘッド以外は何も発生しません。

オプション 2 を使用します。

于 2008-09-02T05:28:28.573 に答える
5

個人的に、次の理由から、多対多のテーブルに合成/代理キー列があります。

  • エンティティテーブルで数値合成キーを使用した場合、リレーションシップテーブルで数値合成キーを使用すると、設計と命名規則の一貫性が維持されます。
  • 将来的には、多対多のテーブル自体が、個々の行への一意の参照を必要とする従属エンティティの親エンティティになる可能性があります。
  • それほど多くの追加のディスクスペースを実際に使用することはありません。

合成キーは、自然/複合キーの代わりにはならず、PRIMARY KEYテーブルの最初の列であるという理由だけでそのテーブルの代わりになるわけでもないので、JoshBerkusの記事に部分的に同意します。ただし、自然キーが常に適切な候補でPRIMARY KEY'sあり、他のテーブルで外部キーとして使用される場合は、使用すべきではないことに同意しません。

于 2008-09-02T10:01:00.010 に答える
5

オプション2は単純なcompundキーを使用し、オプション1は代理キーを使用します。オプション2はほとんどのシナリオで推奨され、適切な候補キーであるという点でリレーショナルモデルに近いものです。

代理キーを使用したい場合があります(オプション1)

  1. 複合キーが時間の経過とともに適切な候補キーであるかどうかはわかりません。特に時間データ(時間とともに変化するデータ)の場合。同じUserIdとWidgetIdを使用してUserWidgetテーブルに別の行を追加したい場合はどうなりますか?Employment(EmployeeId、EmployeeId)について考えてみてください-誰かが後日同じ雇用主のために仕事に戻った場合を除いて、ほとんどの場合は機能します
  2. メッセージ/ビジネストランザクションなど、統合に使用するためのより簡単なキーを必要とするものを作成している場合。多分複製?
  3. 独自の監査メカニズム(または同様のもの)を作成し、キーが長くなりすぎないようにする場合。

経験則として、データをモデル化する場合、ほとんどの連想エンティティ(多対多)はイベントの結果であることがわかります。人が就職したり、アイテムがバスケットに追加されたりします。ほとんどのイベントは、日付または時刻が関連するイベントに時間的に依存します。この場合、代理キーが最良の代替手段となる可能性があります。

したがって、オプション2を選択しますが、完全なモデルがあることを確認してください。

于 2008-09-02T11:49:10.543 に答える
3

前の回答に同意しますが、追加する発言が 1 つあります。リレーションにさらに情報を追加し、同じ 2 つのエンティティ間でより多くのリレーションを許可する場合は、オプション 1 が必要です。

たとえば、ユーザー 1 が userwidget テーブルでウィジェット 664 を使用したすべての時間を追跡したい場合、userid と widgetid は一意ではなくなります。

于 2008-09-02T08:17:49.663 に答える
2

代理数値キーを追加する本当に正当な理由がない限り、オプション2が正解です(オプション1で実行しました)。

代理の数字キー列は「主キー」ではありません。主キーは、技術的には、テーブル内のレコードを一意に識別する列の組み合わせの1つです。

データベースを構築する人は誰でも、Josh Berkusによるこの記事http://it.toolbox.com/blogs/database-soup/primary-keyvil-part-i-7327を読んで、代理の数字キー列と主キーの違いを理解する必要があります。

私の経験では、テーブルに代理数値キーを追加する唯一の本当の理由は、主キーが複合キーであり、別のテーブルで外部キー参照として使用する必要がある場合です。その場合にのみ、テーブルに列を追加することを検討する必要があります。

すべてのテーブルに「id」列があるデータベース構造を見ると、リレーショナルモデルを理解していない人によって設計された可能性があり、Joshの記事で特定された問題の1つ以上が常に表示されます。

于 2008-09-02T06:12:21.523 に答える
2

このシナリオでの主キーの利点は何ですか? 主キーなしのオプションを検討してください: UserWidgets3: WidgetID (FK), UserID (FK)

一意性が必要な場合は、複合キー (UserWidgets2) または一意性制約を使用します。

主キーを使用することによる通常のパフォーマンス上の利点は、主キーを使用して頻繁にテーブルをクエリすることであり、これは高速です。多対多テーブルの場合、通常は主キーでクエリを実行しないため、パフォーマンス上の利点はありません。多対多テーブルは外部キーによってクエリされるため、WidgetID と UserID にインデックスを追加することを検討する必要があります。

于 2008-09-02T05:33:35.923 に答える
1

私は両方で行きます。

私の声を聞いてください:

複合キーは、データの意味を反映する限り、明らかに適切で正しい方法です。質問なし。

ただし、生成された単一の主キー(代理キー)を使用しない限り、Hibernateを適切に機能させるためにさまざまな問題が発生しました。

したがって、論理的および物理的なデータモデルを使用します。論理的なものには複合キーがあります。論理モデルを実装する物理モデルには、代理キーと外部キーがあります。

于 2009-03-22T02:40:35.380 に答える
0

あなたが言ったように、一意性はwidgetidとuseridの組み合わせに由来するため、最初のテーブルのuserwidgetidは必要ありません。

2 番目のテーブルを使用し、外部キーを保持して、widgetid と userid に一意のインデックスを追加します。

そう:

userwidgets( widgetid(fk), userid(fk),
             unique_index(ウィジェット ID、ユーザー ID)
)

データベースがキーのインデックスを計算する必要がないため、余分な主キーを持たないことでパフォーマンスが向上します。上記のモデルでは、このインデックスは (unique_index を介して) 計算されますが、これは理解しやすいと思います。

于 2008-09-02T05:29:15.293 に答える
0

User-Widget の各組み合わせは一意であるため、組み合わせを一意にすることでテーブルでそれを表す必要があります。つまり、オプション 2 を使用します。そうしないと、同じウィジェットとユーザー ID を持つ 2 つのエントリがあり、ユーザー ウィジェット ID が異なる可能性があります。

于 2008-09-02T05:25:18.080 に答える