71

複合キーは一意のオブジェクトIDフィールドを使用するよりもはるかに理想的であり、データベースを構築するときは、単一​​の一意のIDを主キーとして使用しないという考えで構築されたデータベースを継承しました。このデータベース用にRailsフロントエンドを構築していたため、Railsの規則に準拠させるのに苦労しました(ただし、カスタムビューといくつかの追加のgemを使用して複合キーを処理することは可能でした)。

それを書いた人からのこの特定のスキーマ設計の背後にある理由は、データベースが非効率的な方法でIDフィールドを処理する方法と関係があり、インデックスを構築するときに、ツリーの並べ替えに欠陥があります。この説明には深みがなく、私はまだ概念に頭を悩ませようとしています(私は複合キーの使用に精通していますが、100%の時間ではありません)。

誰かが意見を提供したり、このトピックにさらに深みを加えることができますか?

4

15 に答える 15

89

一般的に使用されているほとんどのエンジン (MS SQL Server、Oracle、DB2、MySQL など) では、代理キー システムを使用しても目立った問題は発生しません。サロゲートを使用することでパフォーマンスが向上する場合もありますが、パフォーマンスの問題はプラットフォームに大きく依存します。

大まかに言うと、自然鍵 (ひいては複合鍵) 対代理鍵の議論には長い歴史があり、「正しい答え」は見えません。

自然キー (単数または複合) の引数には、通常、次のものが含まれます。

1) それらはデータモデルですでに利用可能です。モデル化されているほとんどのエンティティには、関係を作成するためのキーのニーズを満たす 1 つ以上の属性または属性の組み合わせが既に含まれています。各テーブルに属性を追加すると、不要な冗長性が組み込まれます。

2) 特定の結合が不要になります。たとえば、顧客コードを持つ顧客と請求書番号を持つ請求書 (どちらも「自然な」キー) があり、特定の顧客コードのすべての請求書番号を取得したい場合は、単純に を使用できます"SELECT InvoiceNumber FROM Invoice WHERE CustomerCode = 'XYZ123'"。従来の代理キー アプローチでは、SQL は次のようになります"SELECT Invoice.InvoiceNumber FROM Invoice INNER JOIN Customer ON Invoice.CustomerID = Customer.CustomerID WHERE Customer.CustomerCode = 'XYZ123'"

3) それらは、データ モデリングへのより普遍的に適用可能なアプローチに貢献します。自然キーを使用すると、異なる SQL エンジン間で同じ設計をほとんど変更せずに使用できます。多くの代理キー アプローチでは、キーの生成に特定の SQL エンジン手法を使用しているため、さまざまなプラットフォームに実装するには、データ モデルをより特殊化する必要があります。

代理キーの引数は、SQL エンジン固有の問題を中心に展開する傾向があります。

1) ビジネス要件/ルールが変更されたときに、属性を簡単に変更できます。これは、データ属性を単一のテーブルに分離できるためです。これは主に、DOMAIN などの標準 SQL 構造を効率的に実装しない SQL エンジンの問題です。属性が DOMAIN ステートメントによって定義されている場合、ALTER DOMAIN ステートメントを使用してスキーマ全体で属性を変更できます。SQL エンジンが異なれば、ドメインを変更するためのパフォーマンス特性も異なります。また、一部の SQL エンジンは DOMAINS をまったく実装していません。そのため、データ モデラーは代理キーを追加してこれらの状況を補い、属性を変更する機能を向上させます。

2) 自然キーよりも並行性の実装が容易になります。自然キーの場合、2 人のユーザーが同じ情報セット (顧客行など) を同時に操作しているときに、ユーザーの 1 人が自然キーの値を変更すると、2 番目のユーザーによる更新は失敗します。更新はデータベースに存在しなくなりました。サロゲート キーの場合、可変の顧客コードではなく、不変の ID 値がデータベース内の行の識別に使用されるため、更新は正常に処理されます。ただし、2 番目の更新を許可することが常に望ましいとは限りません。顧客コードが変更された場合、行の実際の「ID」が変更されているため、2 番目のユーザーが変更を続行できない可能性があります。間違った行を更新しています。代理キーも自然キーも、単独ではこの問題に対処できません。

3) 自然キーよりも優れたパフォーマンスを発揮します。パフォーマンスは、SQL エンジンの影響を最も直接的に受けます。異なる SQL エンジンを使用して同じハードウェアに実装された同じデータベース スキーマは、多くの場合、SQL エンジンのデータ ストレージおよび検索メカニズムにより、パフォーマンス特性が大幅に異なります。一部の SQL エンジンは、顧客コードなどの同じ属性がデータベース スキーマの複数の場所に現れる場合、データが実際に重複して格納されるフラット ファイル システムに非常によく似ています。SQL エンジンによるこの冗長ストレージは、データまたはスキーマを変更する必要がある場合にパフォーマンスの問題を引き起こす可能性があります。他の SQL エンジンは、データ モデルとストレージ/検索システムをより適切に分離し、データとスキーマをより迅速に変更できるようにします。

4) 代理キーは、特定のデータ アクセス ライブラリと GUI フレームワークでより適切に機能します。ほとんどの代理キー設計は同種の性質を持っているため (例: すべてのリレーショナル キーは整数)、データ アクセス ライブラリ、ORM、および GUI フレームワークは、データに関する特別な知識を必要とせずに情報を操作できます。自然キーは、異種の性質 (異なるデータ型、サイズなど) のため、自動化または半自動化されたツールキットおよびライブラリではうまく機能しません。組み込み SQL データベースなどの特殊なシナリオでは、特定のツールキットを念頭に置いてデータベースを設計することが許容される場合があります。他のシナリオでは、データベースは企業の情報リソースであり、複数のプラットフォーム、アプリケーション、レポート システム、およびデバイスから同時にアクセスされるため、特定のライブラリまたはフレームワークに重点を置いて設計された場合、適切に機能しません。加えて、

私は(明らかに)ナチュラルキーの側に落ちる傾向がありますが、私はそれについて熱狂的ではありません. 私が働いている環境では、私が設計を支援する特定のデータベースがさまざまなアプリケーションで使用される可能性があるため、データ モデリングの大部分に自然キーを使用し、サロゲートを導入することはめったにありません。ただし、サロゲートを使用する既存のデータベースを再実装しようとはしません。代理キー システムは問題なく機能します。すでに正常に機能しているものを変更する必要はありません。

各アプローチのメリットについて説明している優れたリソースがいくつかあります。

http://www.google.com/search?q=natural+key+surrogate+key

http://www.agiledata.org/essays/keys.html

http://www.informationweek.com/news/software/bi/201806814

于 2008-10-01T22:38:55.007 に答える
33

私は 15 年間データベース アプリケーションを開発してきましたが、代理キーよりも非代理キーの方が適しているケースにまだ遭遇したことがありません。

そのようなケースが存在しないと言っているわけではありません。データベースにアクセスするアプリケーションを実際に開発するという実際的な問題を考慮に入れると、通常、代理キーの利点が非暗号化の理論的な純度を圧倒し始めると言っているだけです。 -代理キー。

于 2008-10-01T19:05:54.100 に答える
22

主キーは一定で無意味である必要があります。非代理キーは通常、一方または両方の要件を満たしていないため、最終的には失敗します

  • キーが一定でない場合は、将来の更新の問題が発生し、非常に複雑になる可能性があります

  • キーに意味がない場合は、変更される可能性が高くなります。つまり、一定ではありません。上記を参照

簡単で一般的な例を見てみましょう。在庫アイテムのテーブルです。アイテム番号(SKU番号、バーコード、パーツコードなど)を主キーにしたくなるかもしれませんが、1年後にはすべてのアイテム番号が変更され、非常に厄介な更新が残ります。データベースの問題...

編集:哲学的よりも実用的な追加の問題があります。多くの場合、何らかの方法で特定の行を検索し、後でそれを更新するか、もう一度検索します(またはその両方)。複合キーを使用すると、追跡するデータが増え、WHERE句で再検索または更新(または削除)するための制約が増えます。その間に、主要なセグメントの1つが変更された可能性もあります。サロゲートキーを使用すると、保持する値(サロゲートID)は常に1つだけであり、定義上、変更することはできません。これにより、状況が大幅に簡素化されます。

于 2008-10-01T19:16:19.440 に答える
11

データベースを作成した人は、素晴らしい自然キーと代理キーの議論の自然キー側にいるようです。

IDフィールドのbtreeに関する問題については聞いたことがありませんが、これについても深く研究したことはありません...

私は代理キーの側に落ちます。他のテーブルで1つの値しか繰り返さないため、代理キーを使用するときの繰り返しは少なくなります。人間が手でテーブルに参加することはめったにないので、数字であるかどうかは関係ありません。また、インデックスで検索する固定サイズの列は1つしかないため、サロゲートの主キーによる検索時間も短いと考えて間違いありません。

于 2008-10-01T18:53:37.827 に答える
5

'unique(object)ID'フィールドを使用すると結合が単純化されますが、他の(場合によっては複合)キーを引き続き一意にすることを目指す必要があります。null以外の制約を緩和せず、一意の制約を維持してください。

DBMSが一意の整数を効果的に処理できない場合、大きな問題が発生します。ただし、「一意の(オブジェクト)ID」と他のキーの両方を使用すると、他のキーよりも多くのスペース(インデックス用)が使用され、挿入操作ごとに更新される2つのインデックスがあります。したがって、これは景品ではありませんが、元のキーを維持している限り、問題はありません。他のキーを削除すると、システムの設計が破られます。すべての地獄は最終的には解き放たれます(そしてあなたはその地獄が解き放たれたことに気付くかもしれませんし、そうでないかもしれません)。

于 2008-10-01T18:46:05.130 に答える
5

私は基本的にサロゲート キー チームのメンバーであり、JeremyDWill によってここに提示されたような議論を理解して理解しているとしても、「自然な」キーがサロゲートよりも優れているケースをまだ探しています ...

この問題を扱う他の投稿では、通常、リレーショナル データベースの理論とデータベースのパフォーマンスについて言及しています。この場合は常に忘れられているもう 1 つの興味深い議論は、テーブルの正規化コードの生産性に関連しています。

テーブルを作るたびに時間を無駄にしようか

  1. 主キーとその物理的特性 (タイプ、サイズ) を特定する
  2. コードで参照するたびにこれらの特性を覚えていますか?
  3. チーム内の他の開発者に私の PK の選択を説明しますか?

私の答えは、これらすべての質問に対するノーです。

  1. 人のリストを扱うとき、「最適な主キー」を特定しようとして時間を無駄にしているわけではありません。
  2. computer" " テーブルの主キーが 64 文字の長さの文字列であることを思い出したくありません(Windows は、コンピュータ名にそれだけの文字数を受け入れますか?)。
  3. 私の選択を他の開発者に説明したくはありませんが、そのうちの 1 人が最終的に次のように言うでしょう。コンピュータネーム?"。

そこで、私は過去 5 年間、非常に基本的なルールに従って作業してきました。各テーブル (' ' と呼びましょう)には、uniqueIdentifier 型myTableの ' ' という名前の最初のフィールドがあります。id_MyTableこのテーブルが ' ' テーブルのような「多対多」の関係をサポートしていて、 ' ' と ' ' のComputerUser組み合わせが非常に受け入れられる主キーを形成している場合でも、私はこの ' ' フィールドを uniqueIdentifier として作成することを好みます。ルールを守るだけ。id_Computerid_Userid_ComputerUser

主な利点は、コード内での主キーや外部キーの使用について気にする必要がないことです。テーブル名がわかれば、PK の名前とタイプがわかります。データ モデルにどのリンクが実装されているかがわかれば、テーブルで使用できる外部キーの名前がわかります。

私のルールが最良のルールかどうかはわかりません。しかし、それは非常に効率的なものです!

于 2008-10-02T20:12:56.473 に答える
4

新しいアーキテクチャを開発するための実用的なアプローチは、何千もの複数列の非常にユニークなレコードを含むテーブルの代理キーと、短い説明テーブルの複合キーを利用するものです。私は通常、大学が代理キーの使用を指示しているのに対し、現実世界のプログラマーは複合キーを好みます。どちらか一方だけでなく、適切なタイプの主キーをテーブルに適用する必要があります。

于 2008-10-21T20:33:13.730 に答える
3

自然キーを使用すると、永続層として自動ORMを使用することは悪夢になります。また、複数の列の外部キーは互いにオーバーラップする傾向があり、これにより、関係をOOの方法でナビゲートおよび更新するときにさらに問題が発生します。

それでも、固有の制約で自然キーを変換し、自動生成されたIDを追加することができます。これは外部キーの問題を取り除くものではありませんが、それらは手動で変更する必要があります。うまくいけば、複数の列と重複する制約がすべての関係の少数派になるので、最も重要な場所でリファクタリングに集中できます。

自然なpkには動機と使用法のシナリオがあり、悪いことではありません(tm)、ORMとうまくやっていけない傾向があります。

私の考えでは、他の概念と同様に、自然キーとテーブルの正規化は、ブラインド設計の制約としてではなく、賢明な場合に使用する必要があります。

于 2008-10-01T18:55:51.457 に答える
3

ここでは簡潔に説明します。最近の複合主キーは良くありません。可能であれば代理の任意のキーを追加し、一意の制約によって現在のキー スキームを維持します。ORM は幸せで、あなたも幸せで、元のプログラマーはそれほど幸せではありませんが、彼があなたの上司でない限り、彼はそれを処理することができます。

于 2008-10-01T19:29:18.113 に答える
2

複合キーは優れている可能性があります-パフォーマンスに影響を与える可能性があります-しかし、一意の(代理)キーが唯一の答えではないのとほぼ同じように、それらが唯一の答えではありません。

私が懸念しているのは、複合キーを選択する理由のあいまいさです。多くの場合、技術的なことについての曖昧さは、理解の欠如を示しています-おそらく、本や記事で、他の誰かのガイドラインに従っているかもしれません...。

単一の一意のIDに問題はありません。実際、アプリケーションがデータベースサーバーに接続されていて、使用しているデータベースを選択できる場合は、すべてが適切であり、キーを使用してほとんど何でもできます。それほどひどく苦しむことはありません。

単一の答えがないので、これについて多くのことが書かれています。熟練した方法で注意深く適用する必要がある方法とアプローチがあります。

IDがデータベースによって自動的に提供されることに多くの問題がありました。可能な限り回避しますが、それでも時々使用します。

于 2008-10-01T19:22:09.660 に答える
2

私は経験豊富な人ではありませんが、ここでidとして主キーを使用することに賛成です。例を使用した説明です。

外部データの形式は、時間の経過とともに変化する可能性があります。たとえば、本のISBNは、本の表で優れた主キーになると考えるかもしれません。結局のところ、ISBNはユニークです。しかし、この特定の本が書かれているので、米国の出版業界は、すべてのISBNに追加の数字が追加されるため、大きな変化に向けて準備を進めています。書籍の表の主キーとしてISBNを使用した場合、この変更を反映するために各行を更新する必要があります。しかし、別の問題が発生します。データベースには、主キーを介してbooksテーブルの行を参照する他のテーブルがあります。これらのすべての参照を最初に調べて更新しない限り、booksテーブルのキーを変更することはできません。これには、外部キー制約の削除、テーブルの更新、booksテーブルの更新、そして最後に制約の再確立が含まれます。全体として、これはちょっとした苦痛です。独自の内部値を主キーとして使用すると、問題は解決します。サードパーティがやって来て、スキーマを変更するように任意に指示することはできません。独自のキースペースを制御します。また、ISBNなどを変更する必要がある場合は、データベース内の既存の関係に影響を与えることなく変更できます。事実上、行の編み方を、それらの行のデータの外部表現から切り離しました。

説明はかなり本っぽいですが、もっと簡単に説明できると思います。

于 2010-04-21T07:06:47.007 に答える
2

...データベースが非効率的な方法でIDフィールドを処理する方法と、インデックスを構築するときのツリーソートに欠陥があります...

これはほぼ間違いなくナンセンスでしたが、異なるセッションから増加する番号を高いレートで PK に割り当てる際のインデックス ブロックの競合の問題に関連している可能性があります。その場合、REVERSE KEY インデックスが役立ちますが、ブロック分割アルゴリズムの変更によりインデックス サイズが大きくなります。http://download.oracle.com/docs/cd/B19306_01/server.102/b14220/schema.htm#sthref998

特に、ツールセットでより迅速な開発を支援する場合は、総合的に行ってください。

于 2008-10-01T20:09:46.223 に答える
1

両方を行うことができます。大企業のデータベースは、1 回限りのクエリやデータのインポートを実行する人間の DBA を含む複数のアプリケーションで使用される可能性が高いため、ORM システムの利益のためだけにデータベースを設計することは、常に実用的または望ましいとは限りません。

私が最近行う傾向があるのは、各テーブルに「RowID」プロパティを追加することです。このフィールドは GUID であり、各行に固有です。これは主キーではなく、自然キーです (可能な場合)。ただし、このデータベース上で動作する ORM レイヤーは、RowID を使用して派生オブジェクトを識別できます。

したがって、次のようになる可能性があります。

CREATE TABLE dbo.Invoice (
  顧客 ID varchar(10),
  CustomerOrderNo varchar(10),
  InvoiceAmount 金額が null ではない、
  コメント nvarchar(4000),
  RowId uniqueidentifier が null ではない default(newid()),

  主キー(CustomerId、CustomerOrderNo)
)

したがって、DBA は満足し、ORM アーキテクトも満足し、データベースの整合性が保たれます!

于 2008-10-24T15:03:11.353 に答える
1

@ジェレミーDWill

議論に必要なバランスを提供していただきありがとうございます。特にsの情報ありがとうございDOMAINます。

実際には、一貫性を保つためにシステム全体で代理キーを使用していますがトレードオフが伴います。サロゲート キーを使用して悪態をつく最も一般的な原因は、正規値の短いリストを含むルックアップ テーブルがある場合です。値を作成しただけであれば、使用するスペースが少なくなり、すべてのクエリがより短く、より簡単に、より高速になります。テーブルに参加する代わりに PK を使用します。

于 2008-10-02T08:42:11.813 に答える
0

自動生成された整数 ID フィールドをリレーショナル データベースで議論するときにカバーされていないものをここに追加したかっただけです (私はそれらを頻繁に目にするため)。

これにより、自動的に複合 ID が使用されるようになるとは言いませんが、(まだ一意である) テーブルにさらに多くのデータを論理的に追加できたとしても、自動生成された単一の整数アイデンティティは、これが起こらないようにすることができます。

はい、ほとんどの状況ではありそうもないことを認識しています.64ビット整数を使用すると、多くのヘッドルームが得られます。現実的には、このようなオーバーフローが発生した場合、データベースはおそらく別の方法で設計されているはずです.

しかし、それは誰かがそれを行うことを妨げるものではありません...特定のファーストフード会社のグローバルレベルですべてのトランザクションを保存することが期待される単一の自動生成された 32 ビット整数を ID として使用するテーブルは、次のように失敗します。挿入しようとするとすぐに、2,147,483,648 番目のトランザクションになります (これは完全に実行可能なシナリオです)。

注意すべきことは、人々は大げさに見過ごしたり、完全に無視したりする傾向があるということです。テーブルが定期的に挿入される場合は、時間の経過とともにデータが蓄積される頻度と量、および整数ベースの識別子を使用する必要があるかどうかを考慮する必要があります。

于 2014-06-08T15:52:05.040 に答える