20

私は、さまざまなソースから発信されたデータを格納するために使用されるデータベースの設計に取り組んでいます。保存しているインスタンスには、元のソースによって一意のIDが割り当てられています。保存する各インスタンスには、ソースに関する情報と、このソースによって関連付けられたIDが含まれている必要があります。

例として、問題を説明する次の表について考えてみます。

----------------------------------------------------------------
| source_id | id_on_source | data                              |
----------------------------------------------------------------
| 1         | 17600        | ...                               |
| 1         | 17601        | ...                               |
| 2         | 1            | ...                               |
| 3         | 1            | ...                               |
----------------------------------------------------------------

id_on_sourceはソースごとに一意ですがid_on_source、異なるソースで同じものが見つかる可能性があることに注意してください。

私はリレーショナルデータベースについて十分に理解していますが、専門家や経験豊富なユーザーからはほど遠いです。この設計で私が直面する問題は、主キーとして何を使用すべきかということです。データは、の複合主キーの使用を指示しているようです(source_id, id_on_source)。少しグーグルした後、複合主キーの長所と短所についていくつかの白熱した議論を見つけましたが、少し混乱しました。

このテーブルは他のテーブルと1対多の関係にあるため、他のテーブルの外部キーで参照されます。

私は特定のものに縛られておらず、議論のためにそれが重要かどうかはわかりませんが、とRDBMSで作業することを好むとしましょう。SQLiteMySQL

この場合、複合外部キーを使用することの長所と短所は何ですか?どちらがいいですか?

4

8 に答える 8

31

個人的には、複合主キーは苦痛だと思います。「sources」テーブルに結合するすべてのテーブルについて、source_id フィールドと id_on_source フィールドの両方を追加する必要があります。

ソース テーブルに標準の自動インクリメント主キーを作成し、source_id 列と id_on_source 列に一意のインデックスを追加します。

これにより、ソース テーブルの ID だけを他のテーブルの外部キーとして追加できます。

一般的に、多くのフレームワークおよびツール製品内での複合主キーのサポートは、せいぜい「パッチがあり」、他の製品には存在しないこともわかりました。

于 2009-09-05T11:24:16.127 に答える
14

複合キーは管理が難しく、結合も遅いです。サマリー テーブルを作成しているので、代理キー (つまり、自動インクリメント/ID 列) を使用します。自然キー列はそのままにしておきます。

これには、他にも多くの利点があります。主に、会社と合併し、同じソースの 1 つを持っているがキーを再利用している場合、代理キーを使用していないと問題が発生します。

これは、データ ウェアハウジングで広く認められているベスト プラクティス (実際に行っている作業よりもはるかに大きな作業ですが、それでも関連性があります) であり、正当な理由があります。サロゲートは、データの整合性と迅速な結合を提供します。自然キーを使用するとすぐに火傷を負う可能性があるため、自然キーを識別子として使用することは避け、インポート プロセスでのみ使用してください。

于 2009-09-05T11:29:06.347 に答える
8

これら 2 つの属性の組み合わせが一意であるというビジネス要件があります。UNIQUEしたがって、これら 2 つの属性に制約を設ける必要があります。その制約を「プライマリ」と呼ぶかどうかUNIQUEは、実際には単なる好みであり、ドキュメントを除いて大きな影響はありません。

唯一の問題は、追加の列を追加してマークするかどうかですUNIQUE。そうする唯一の理由はパフォーマンスであり、これは正当な理由です。

個人的には、すべてのデータベースを本質的にグラフに変えるアプローチは好きではありません。生成された列は本質的にポインターであり、あるデータベースから次のデータベースへとトラバースするだけです。それはリレーショナル システムの素晴らしさをすべて捨て去っていると思います。一歩下がって考えてみると、ビジネスにとってまったく意味のない一連のコラムを導入していることになります。私の関連するブログ投稿に興味があるかもしれません。

于 2009-09-05T17:10:25.463 に答える
6

複合キーは、非常に自然で記述的なデータモデルを作成すると思います。私の経験はOracleからのものであり、複合PKを作成するときに技術的な問題はないと思います。実際、データディクショナリを分析する人は誰でも、テーブルについて何かをすぐに理解するでしょう。あなたの場合、各source_idが一意のid_on_sourceを持っている必要があることは明らかです。

自然キーの使用はしばしば熱い議論を引き起こしますが、私が一緒に仕事をしている人々は、優れたデータモデルの観点から自然キーのようです。

于 2009-09-05T11:42:49.820 に答える
3

私が複合主キーを使用するのは、ほとんどの場合、キーの上位部分が別のテーブルへのキーである場合だけです。たとえば、OrderId + LineNumber の主キーを持つ OrderLineItem テーブルを作成するとします。OrderLineItem テーブルに対する多くのアクセスは、「(orderid) を使用して orderlineitem を注文する」またはそのバリエーションになるため、これは多くの場合便利です。また、データベース ダンプを参照して、どのライン アイテムがどのオーダーに関連付けられているかを簡単に把握できます。

他の人が指摘しているように、結合にはすべてのピースを含める必要があるため、複合キーは他のほとんどの状況では苦痛です。入力することが多くなるため、ミスの可能性が高くなり、クエリが遅くなるなどです。

2 つの部分からなるキーは悪くありません。私はそれらをかなり頻繁に行います。3 分割キーを使用するのは気が進まない。3 部構成以上の場合は、忘れてください。

あなたの例では、複合キーを使用しても得られるものはほとんどないと思います。新しいシーケンス番号を発明し、ソースとソース キーを通常の属性にします。

于 2009-09-05T22:49:15.020 に答える
2

多くの複合キーを使用して問題が発生したため、お勧めしません (以下で詳しく説明します)。また、ユーザーのミスをロールバックしようとするときに、(自然ではなく) 独立/代理キーに利点があることもわかりました。 . 問題は、一連のリレーションを介して、1 つのテーブルが 2 つのテーブルを結合し、コンポジットの各行部分が同じであるということでした (これは、第 3 正規形 (親の 2 つの部分の比較) で適切でした)。結合テーブルの複合リレーションシップのその部分の重複を排除しました (そのため、parent1ID、other1ID、parent2ID、other2ID の代わりに、parentID、other1ID、other2ID がありました) が、リレーションは主キーへの変更を更新できませんでした。各ルートで2回やって途中で失敗。

于 2011-11-16T10:05:19.053 に答える
1

一部の人々は、グローバル一意ID(GUID)の使用を推奨しています。サブスクリプションの更新を伴うレプリケーションとトランザクションレプリケーションのマージでは、uniqueidentifier列を使用して、テーブルの複数のコピー間で行が一意に識別されるようにします。値が作成時にグローバルに一意である場合、一意にするためにsource_idを追加する必要はありません。


uniqueidは優れた主キーですが、通常は、クラスター化インデックスとして別の自然な(必ずしも一意ではない)キーを使用する方がよいことに同意します。たとえば、uniqueidが従業員を識別するPKである場合、クラスター化されたインデックスを部門にすることができます(selectステートメントが通常特定の部門内のすべての従業員を取得する場合)。クラスター化されたインデックスとしてunqiqueidを使用する場合は、NEWSEQUENTIALID()関数を参照してください。これにより、シーケンシャルなuniqueid値が作成され、(シーケンシャルであるため)クラスタリングのパフォーマンスが向上します。

于 2009-09-05T11:35:18.647 に答える
1

ID 列を追加すると、1 つではなく 2 つの一意性制約を適用する必要が生じます。

自然に現れるキーの代わりに、その追加の ID 列を他の参照テーブルの外部キーとして使用すると、元の soruce_ID と ID_on_source が必要なすべてのケースで、より多くの結合を行う必要があります参照テーブル。

于 2009-09-05T16:51:57.090 に答える