278

テーブルを設計するとき、私は一意の 1 つの列を持ち、主キーを作成するという習慣を身につけました。これは、要件に応じて次の 3 つの方法で実現されます。

  1. 自動インクリメントする ID 整数列。
  2. 一意の識別子 (GUID)
  3. 行識別子列として機能する短い文字 (x) または整数 (またはその他の比較的小さい数値型) の列

数値 3 は、かなり小さなルックアップに使用されます。ほとんどの場合、一意の静的な長さの文字列コード、または年やその他の数値などの数値を持つ可能性がある読み取りテーブルです。

ほとんどの場合、他のすべてのテーブルには、自動インクリメント整数または一意の識別子の主キーがあります。

質問 :-)

私は最近、一貫した行識別子を持たず、主キーが現在さまざまな列にクラスター化されているデータベースでの作業を開始しました。いくつかの例:

  • 日時/文字
  • 日時/整数
  • 日時/varchar
  • char/nvarchar/nvarchar

これには有効なケースがありますか?これらのケースでは、ID 列または一意の識別子列を常に定義していました。

さらに、主キーがまったくないテーブルが多数あります。正当な理由があるとすれば、それは何ですか?

なぜテーブルがそのまま設計されたのかを理解しようとしていますが、私には大きな混乱のように見えますが、それには正当な理由があったのかもしれません。

答えを解読するのに役立つ 3 番目の質問: 複合主キーを構成するために複数の列が使用されている場合、この方法と代理/人工キーに比べて特定の利点はありますか? 私は主にパフォーマンス、メンテナンス、管理などに関して考えていますか?

4

21 に答える 21

282

私はいくつかのルールに従います。

  1. 主キーは必要なだけ小さくする必要があります。数値型は文字形式よりもはるかにコンパクトな形式で格納されるため、数値型を優先します。これは、ほとんどの主キーが別のテーブルの外部キーであり、複数のインデックスで使用されるためです。キーが小さいほど、インデックスが小さくなり、使用するキャッシュ内のページが少なくなります。
  2. 主キーは決して変更しないでください。主キーを更新することは、常に問題外であるべきです。これは、複数のインデックスで使用され、外部キーとして使用される可能性が最も高いためです。1 つの主キーを更新すると、変更の波及効果が生じる可能性があります。
  3. 「問題の主キー」をロジック モデルの主キーとして使用しないでください。たとえば、パスポート番号、社会保障番号、従業員契約番号などは、これらの「自然キー」が実際の状況で変化する可能性があるためです。一貫性を確保するために必要な場合は、これらに UNIQUE 制約を追加してください。

サロゲートと自然キーについては、上記のルールを参照してください。自然キーが小さく、変更されない場合は、主キーとして使用できます。自然キーが大きいか変更される可能性がある場合は、代理キーを使用します。主キーがない場合でも、代理キーを作成します。これは、経験上、スキーマに常にテーブルを追加し、主キーを配置したいと思うからです。

于 2008-12-03T19:25:46.970 に答える
98

自然鍵と人工鍵は、データベース コミュニティの間での宗教的な議論のようなものです。この記事や他のリンク先の記事を参照してください。私は人工的な鍵を常に持つことにも、絶対に持たないことにも賛成しません。ケースバイケースで判断します。たとえば、次のようになります。

  • 米国の州: テキサスの state_id=1 ではなく、state_code (テキサスの場合は「TX」など) を使用します。
  • 従業員: 他に機能するものを見つけるのが難しいため、通常は人工的な employee_id を作成します。SSN または同等のものは機能する可能性がありますが、SSN をまだ提供していない新しいジョイナーなどの問題が発生する可能性があります。
  • 従業員の給与履歴: (employee_id, start_date)。人為的な employee_salary_history_id は作成しません。それはどのような点に役立ちますか(「愚かな一貫性」以外)

人工キーが使用されている場合は常に、自然キーに対する一意の制約も宣言する必要があります。たとえば、必要に応じて state_id を使用しますが、state_code で一意の制約を宣言することをお勧めします。そうしないと、最終的に次のようになります。

state_id    state_code   state_name
137         TX           Texas
...         ...          ...
249         TX           Texas
于 2008-12-03T16:19:27.097 に答える
28

ヒューマンエラーという単純な理由から、自然キーの使用は避けています。自然な一意の識別子(SSN、VIN、アカウント番号など)が利用できることがよくありますが、それらを正しく入力するには人間が必要です。SSNを主キーとして使用している場合、データ入力中に誰かがいくつかの数字を転置し、エラーがすぐに検出されない場合は、主キーを変更する必要があります。

私の主キーはすべてバックグラウンドでデータベースプログラムによって処理され、ユーザーはそれらに気付くことはありません。

于 2011-07-12T20:55:41.877 に答える
26

見過ごされがちなことについての追加コメントです。1 つのサロゲート キーをプライマリとして使用しないと、子テーブルで利点が得られる場合があります。1 つのデータベース内で複数の会社を運営できるように設計されているとします (ホスト型ソリューションなど)。

これらのテーブルと列があるとします。

Company:
  CompanyId   (primary key)

CostCenter:
  CompanyId   (primary key, foreign key to Company)
  CostCentre  (primary key)

CostElement
  CompanyId   (primary key, foreign key to Company)
  CostElement (primary key)

Invoice:
  InvoiceId    (primary key)
  CompanyId    (primary key, in foreign key to CostCentre, in foreign key to CostElement)
  CostCentre   (in foreign key to CostCentre)
  CostElement  (in foreign key to CostElement)

最後のビットが意味をなさない場合Invoice.CompanyIdは、2 つの外部キーの一部であり、1 つはCostCentreテーブルへ、もう 1 つはCostElementテーブルへです。主キーは ( InvoiceId , CompanyId ) です。

このモデルでは、ある会社のCostElementと別の会社のCostCentreをめちゃくちゃにして参照することはできません。CostElement テーブルとCostCentreテーブルで1 つの代理キーがプライマリとして使用され、 Invoice テーブルで外部キー リレーションが使用されていない場合は、そのようになります。

失敗する機会が少ないほど良いです。

于 2008-12-05T10:38:47.063 に答える
13

さまざまなフィールドから主キーを作成することに問題はありません。これはNatural Keyです。

ID 列 (候補フィールドの一意のインデックスに関連付けられている) を使用して、代理キーを作成できます。

それは古い議論です。私はほとんどの状況で代理キーを好みます。

しかし、鍵がないという言い訳はありません。

RE: 編集

ええ、それについては多くの論争があります:D

自然キーが自然な選択であるという事実を除けば、自然キーには明らかな利点はありません。idPersonの代わりに、常にName、SocialNumber、またはそのようなもので考えるでしょう。

代理キーは、自然キーが持ついくつかの問題 (変更の伝播など) に対する答えです。

サロゲートに慣れるにつれて、よりクリーンで扱いやすいように見えます。

しかし、最終的には、それは好みの問題、または考え方の問題であることがわかります。人々は自然キーで「よく考える」が、そうでない人もいる。

于 2008-12-03T16:04:11.947 に答える
12

テーブルには常に主キーが必要です。そうでない場合は、AutoIncrement フィールドにする必要があります。

大量のデータを転送し、(データベースによっては) プロセスが遅くなる可能性があるため、主キーを省略する場合があります。ただし、その後に追加する必要があります。

link table に関するいくつかのコメント、これは正しいです。例外ですが、整合性を維持するためにフィールドは FK である必要があり、場合によっては、リンクの重複が許可されていない場合、これらのフィールドも主キーになる可能性があります...しかし、例外はプログラミングでよくあることなので、単純な形式です。データの整合性を保つために主キーが存在する必要があります。

于 2008-12-03T15:33:49.340 に答える
6

主キーの特別な点は何ですか?

スキーマ内のテーブルの目的は何ですか? テーブルのキーの目的は何ですか? 主キーの特別な点は何ですか? 主キーに関する議論は、主キーがテーブルの一部であり、そのテーブルがスキーマの一部であるという点を見逃しているようです。テーブルとテーブルの関係に最適なものは、使用されるキーを駆動する必要があります。

テーブル (およびテーブルの関係) には、記録したい情報に関する事実が含まれています。これらの事実は、自己完結型で、意味があり、理解しやすく、矛盾のないものでなければなりません。設計の観点から、スキーマに追加またはスキーマから削除された他のテーブルは、問題のテーブルに影響を与えるべきではありません。情報自体にのみ関連するデータを保存する目的がなければなりません。テーブルに何が格納されているかを理解するために、科学研究プロジェクトを実施する必要はありません。同じ目的で保存されるファクトは、複数回保存されるべきではありません。キーは、記録される情報の全体または一部であり、一意であり、プライマリ キーは、テーブルへのプライマリ アクセス ポイントとなる特別に指定されたキーです (つまり、挿入だけでなく、データの一貫性と使用のために選択する必要があります)。パフォーマンス)。

  • ASIDE: 残念なことに、ほとんどのデータベースがアプリケーション プログラマー (私もそうです) によって設計および開発されることの副作用は、アプリケーションまたはアプリケーション フレームワークに最適なものがテーブルのプライマリ キーの選択を左右することが多いことです。これにより、整数キーと GUID キー (これらはアプリケーション フレームワークで簡単に使用できるため) とモノリシック テーブル設計 (メモリ内のデータを表すために必要なアプリケーション フレームワーク オブジェクトの数が減るため) につながります。これらのアプリケーション主導のデータベース設計の決定は、大規模に使用すると、重大なデータの一貫性の問題につながります。このように設計されたアプリケーション フレームワークは、自然にテーブル アット タイムの設計につながります。「部分レコード」はテーブルに作成され、データは時間をかけて入力されます。アプリケーションが適切に機能しない場合、マルチテーブルの相互作用が回避されるか、使用するとデータの一貫性が失われます。これらの設計は、意味のない (または理解しにくい) データ、複数のテーブルにまたがるデータ (現在のテーブルを理解するには他のテーブルを調べる必要があります)、および重複データにつながります。

主キーは必要なだけ小さくすべきだと言われました。キーは必要なだけ大きくするべきだと思います。無意味なフィールドを無作為にテーブルに追加することは避けるべきです。無作為に追加された無意味なフィールドからキーを作成するのはさらに悪いことです。特に、別のテーブルから非主キーへの結合依存関係を破棄する場合はなおさらです。これは、テーブルに適切な候補キーがない場合にのみ妥当ですが、すべてのテーブルに使用すると、スキーマ設計が不適切であることを示しています。

また、主キーの更新は常に問題外であるため、主キーは決して変更されるべきではないとも言われました。ただし、更新は、削除の後に挿入することと同じです。このロジックにより、1 つのキーを持つテーブルからレコードを削除してから、2 番目のキーを持つ別のレコードを追加することは決してありません。サロゲート主キーを追加しても、テーブルに他のキーが存在するという事実は削除されません。テーブルの非主キーを更新すると、他のテーブルが代理キーを介してその意味に依存している場合 (たとえば、ステータスの説明が「処理済み」から「キャンセル済み」に変更された代理キーを持つステータス テーブル)、データの意味が破壊される可能性があります。 ' は間違いなくデータを破損します)。常に問題外であるべきことは、データの意味を破壊することです。

そうは言っても、今日のビジネスに存在する多くの設計が不十分なデータベース (意味のない代理キー付きデータ破損 1NF 巨獣) に感謝しています。これは、適切なデータベース設計を理解している人々の仕事が無限にあることを意味するためです。 . しかし、悲しいことに、それは私をシーシュポスのように感じさせることもありますが、彼は (クラッシュの前に) 401k を 1 つ持っていたに違いありません。データベース設計に関する重要な質問については、ブログや Web サイトには近づかないでください。データベースを設計している場合は、CJ Date を参照してください。SQL Server の Celko を参照することもできますが、最初に鼻をかむ場合に限ります。Oracle 側では、Tom Kyte を参照してください。

于 2013-01-03T18:57:14.270 に答える
5

利用可能な場合は、通常、自然キーが最適です。したがって、datetime/charが行を一意に識別し、両方の部分が行にとって意味がある場合、それは素晴らしいことです。

日時だけが意味があり、文字を追加して一意にする場合は、識別フィールドを使用することもできます。

于 2008-12-03T15:34:08.123 に答える
4

私にとって自然キーと人工キーは、データベースに必要なビジネス ロジックの量の問題です。社会保障番号(SSN) はその好例です。

「データベース内の各クライアントには、SSN が必要です。」バム、完了、それを主キーにして、それで完了です。ビジネス ルールが変更されると、頭がおかしくなることを覚えておいてください。

ビジネスルールを変更した経験があるため、私自身は自然キーが好きではありません。ただし、変更されないことが確実な場合は、いくつかの重要な結合が妨げられる可能性があります。

于 2008-12-03T19:26:21.757 に答える
4

元のデータ構造の設計者には、Steven A. Lowe のロールアップされた新聞療法が必要だと思います。

余談ですが、GUIDをプライマリ キーとして使用すると、パフォーマンスが大幅に低下する可能性があります。私はそれをお勧めしません。

于 2008-12-03T15:32:49.967 に答える
3

私も常に数値 ID 列を使用しています。オラクルでは、number(12,0) (または long ではなく int のもの) を超える本当の理由で number(18,0) を使用します。おそらく、数十億行を取得することについて心配したくないだけです。デブ!

また、基本的な追跡用に作成および変更された列 (タイプ タイムスタンプ) も含めます。

列の他の組み合わせに一意の制約を設定することは気にしませんが、ID、作成、変更されたベースライン要件は本当に気に入っています。

于 2008-12-03T15:35:28.633 に答える
3

自然な主キーを探して、できる限り使用します。

自然キーが見つからない場合は、INT++ よりも GUID を好みます。SQL Server はツリーを使用しており、常にツリーの最後にキーを追加するのは良くないからです。

多対多結合のテーブルでは、外部キーの複合主キーを使用します。

幸運にも SQL Server を使用できるので、プロファイラーとクエリ アナライザーを使用して実行計画と統計を調査し、キーのパフォーマンスを非常に簡単に調べることができます。

于 2008-12-03T19:33:51.663 に答える
2

GUIDは主キーとして使用できますが、適切なタイプの GUID を作成してパフォーマンスを向上させる必要があります。

COMB GUID を生成する必要があります。それとパフォーマンス統計に関する優れた記事は The Cost of GUIDs as Primary Keysです。

また、 SQLでCOMB GUID を構築するコードの一部はUniqueidentifier vs identity ( archive )にあります。

于 2008-12-03T19:49:18.543 に答える
2

複数のフィールドで構成される「複合」または「複合」主キーを使用する必要があります。

これは完全に受け入れられる解決策です。詳細については、こちらを参照してください:)

于 2008-12-03T15:35:22.097 に答える
2

私は常に自動付番または ID フィールドを使用します。

私は、SSN を主キーとして使用していたクライアントのために働いていましたが、HIPAA 規制のために「MemberID」への変更を余儀なくされ、関連するテーブルの外部キーを更新するときに多くの問題が発生しました。ID 列の一貫した基準に固執することで、すべてのプロジェクトで同様の問題を回避することができました。

于 2008-12-03T15:53:28.113 に答える
1

すべてのテーブルに主キーが必要です。それ以外の場合、あなたが持っているのはHEAPです-これは、状況によっては、あなたが望むものかもしれません(たとえば、データがサービスブローカーを介して別のデータベースまたはテーブルに複製されるときの重い挿入負荷)。

行数が少ないルックアップテーブルの場合、INTよりもスペースが少ないため、主キーとして3 CHARコードを使用できますが、パフォーマンスの違いはごくわずかです。それ以外は、関連するテーブルの外部キーで構成された複合主キーを持つ参照テーブルがない限り、常にINTを使用します。

于 2008-12-03T16:29:58.087 に答える
1

この古くからの議論を本当に読みたい場合は、StackOverflowで「自然キー」を検索してください。結果のページを取り戻す必要があります。

于 2008-12-03T16:34:54.677 に答える
0

自然キーの好みについて率直にお話しします。可能な場合は自然キーを使用してください。データベース管理の作業がはるかに簡単になるからです。すべてのテーブルに次の列があるという社内の基準を確立しました。

  • 行 ID (GUID)
  • Creator (文字列。既定値は現在のユーザー名 ( SUSER_SNAME()T-SQL 内))
  • 作成日 (日時)
  • タイムスタンプ

行 ID にはテーブルごとに一意のキーがあり、いずれの場合も行ごとに自動生成され (権限により、だれもそれを編集できなくなります)、すべてのテーブルとデータベースで一意であることが合理的に保証されます。ORM システムで単一の ID キーが必要な場合は、これを使用します。

一方、実際の PK は、可能であれば自然キーです。私の内部ルールは次のようなものです。

  • People - INT などの代理キーを使用します。内部の場合は、Active Directory ユーザー GUID を選択できます
  • ルックアップ テーブル (例: StatusCodes) - 短い CHAR コードを使用します。INT よりも覚えやすく、多くの場合、紙のフォームやユーザーは簡潔にするためにそれを使用します (たとえば、Status = "E" は "Expired"、"A" は "Approved"、"NADIS" は "No Asbestos Detected" を表します)。サンプル」)
  • リンク テーブル - FK の組み合わせ (例EventId, AttendeeId)

したがって、理想的には、自然で、人間が判読でき、記憶に残る PK と、ORM に適したテーブルごとに 1 つの ID を持つ GUID になります。

警告: 私が維持しているデータベースは、数百万または数十億ではなく、数十万のレコードを扱う傾向があるため、私のアドバイスを禁ずる大規模なシステムの経験がある場合は、遠慮なく無視してください!

于 2008-12-30T22:34:58.113 に答える
0

私たちは多くの結合を行っており、複合主キーはパフォーマンスを浪費しています。単純な int または long は、2 番目の候補キーを導入している場合でも、多くの問題を処理しますが、3 つのフィールドよりも 1 つのフィールドに結合する方がはるかに簡単で理解しやすいです。

于 2008-12-03T15:41:19.420 に答える