web-dev-qa-db-ja.com

複合主キーは悪い習慣ですか?

複合主キーが悪い習慣であるかどうかを知り、そうでない場合は、どのシナリオを使用することが推奨されますか。

私の質問はこれに基づいています 記事

databases design mistakes

複合主キーに関する部分:

悪い実践No. 6:複合主キー

現在、多くのデータベース設計者は、2つ以上のフィールドの組み合わせで定義された複合フィールドではなく、整数IDの自動生成フィールドを主キーとして使用することについて話しているため、これは問題のある点です。これは現在「ベストプラクティス」として定義されており、個人的には同意する傾向があります。

Image of a composite primary key

ただし、これは単なる慣例であり、もちろん、DBEでは複合主キーを定義できます。これは、多くの設計者が避けられないと考えています。したがって、冗長性と同様に、複合主キーは設計上の決定事項です。

ただし、複合主キーを含むテーブルに数百万の行が含まれることが予想される場合、複合キーを制御するインデックスが、CRUD操作のパフォーマンスが非常に低下するところまで大きくなる可能性があることに注意してください。その場合、インデックスが十分にコンパクトで、一意性を維持するために必要なDBE制約を確立する単純な整数ID主キーを使用する方がはるかに優れています。

14
hackvan

"Composite keys as PRIMARY KEY is bad practice"の使用はまったくナンセンスです!

複合PRIMARY KEYsは、多くの場合非常に「良いこと」であり、日常生活で発生する自然な状況をモデル化する唯一の方法です。

古典的なDatabases-101の学生とコースの指導例、および多くの学生が講じた多くのコースを考えてみてください。

テーブルコースと学生を作成します。

CREATE TABLE course
(
  course_id SERIAL,
  course_year SMALLINT NOT NULL,
  course_name VARCHAR (100) NOT NULL,
  CONSTRAINT course_pk PRIMARY KEY (course_id)
);


CREATE TABLE student
(
  student_id SERIAL,
  student_name VARCHAR (50),
  CONSTRAINT student_pk PRIMARY KEY (student_id)
);

PostgreSQL方言 (および MySQL )の例を紹介します-微調整が必​​要なすべてのサーバーで機能するはずです。

さて、あなたは明らかにどの学生がどのコースを取っているかを追跡したいのでjoining tableと呼ばれるもの(linkingmany-to-manyまたはm-to-nテーブルとも呼ばれます)があります。それらは、より専門的な専門用語では associative entities としても知られています!

1コースには多数の学生が参加できます。
1受講可能多数コース。

したがって、結合テーブルを作成します

CREATE TABLE course_student
(
  cs_course_id INTEGER NOT NULL,
  cs_student_id INTEGER NOT NULL,

  -- now for FK constraints - have to ensure that the student
  -- actually exists, ditto for the course.

  CREATE CONSTRAINT cs_course_fk FOREIGN KEY (cs_course_id) REFERENCES course (course_id),
  CREATE CONSTRAINT cs_student_fk FOREIGN KEY (cs_student_id) REFERENCES student (student_id)
);

さて、このテーブルに賢明にPRIMARY KEYを与えるonly方法は、そのKEYをコースと生徒の組み合わせにすることです。そのようにすると、以下を取得できません。

  • 学生とコースの組み合わせの複製

    • コースは同じ学生を1回のみ登録できます。

    • 学生は同じコースに一度だけ登録できます

  • また、学生ごとのコースで既製の検索KEYもある-別名a カバリングインデックス

  • 学生のいないコースや、コースを履修していない学生を見つけるのは簡単です。

    -db-fiddle example には、CREATE TABLEに組み込まれたPK制約があります-これはどちらの方法でも実行できます。私はすべてをCREATE TABLEステートメントに含めることを好みます。


ALTER TABLE course_student 
ADD CONSTRAINT course_student_pk 
PRIMARY KEY (cs_course_id, cs_student_id);

これで、コースによる学生の検索が遅いことがわかった場合は、UNIQUE INDEXを(sc_student_id、sc_course_id)で使用できます。

ALTER TABLE course_student 
ADD CONSTRAINT course_student_sc_uq  
UNIQUE (cs_student_id, cs_course_id);

noインデックスを追加するための特効薬-それらはwillINSERTsとUPDATEsを遅くしますが、非常に大きなメリットがあります- 減少SELECT回!知識と経験を踏まえてインデックスを作成するかどうかは開発者次第ですが、コンポジットPRIMARY KEYsがalways badであると言うのは明らかに間違っています。

テーブルを結合する場合、それらは通常onlyPRIMARY KEYです。テーブルの結合は、ビジネスや自然、または私が考えることができるほぼすべての領域で何が起こるかをモデル化する唯一の方法でもあります。

このPKは、検索の高速化に役立つ covering index としても使用されます。この場合、(course_id、student_id)を定期的に検索していると特に便利です。

これは、コンポジットPRIMARY KEYが非常に優れたアイデアであり、現実をモデル化する唯一の健全な方法のほんの一例です!私の頭の上で、私はmany manyについて考えることができます。

私自身の作品の例!

Flight_id、出発空港と到着空港のリスト、および関連する時刻が含まれているフライトテーブル、および乗務員が含まれているcabin_crewテーブルについて考えてみましょう。

これをモデル化できるonlyの正しい方法は、flight_idとcrew_idを属性として含むflight_crewテーブルを作成することです。唯一の正しいPRIMARY KEYは、2つのフィールドの複合キーを使用することです。

31
Vérace

中途半端な考え方:「主キー」は、テーブル内のデータを検索するために使用される唯一の一意のキーである必要はありませんが、データ管理ツールがデフォルトの選択として提供しています。したがって、2つの列の複合、またはランダム(おそらくシリアル)で生成された数値をテーブルキーとして使用するかどうかを選択するには、2つの異なるキーを一度に使用できます。

行を表すことができる適切な一意の用語がデータ値に含まれている場合、「合成」キーを使用するよりも、複合であっても「主キー」として宣言するほうがよいでしょう。合成キーは技術的な理由でパフォーマンスが向上する可能性がありますが、サービスを機能させるために他の方法を実行する必要がない限り、実際の用語を主キーとして指定して使用することが私のデフォルトの選択です。

Microsoft SQL Serverには、インデックス順にデータの物理ストレージを制御する「クラスター化インデックス」の明確だが関連する機能があり、他のインデックス内でも使用されます。既定では、主キーはクラスター化インデックスとして作成されますが、できればクラスター化インデックスを作成した後で、代わりに非クラスター化を選択できます。したがって、整数のIDで生成された列をクラスター化インデックスとして、そしてたとえばファイル名nvarchar(128文字)を主キーとして持つことができます。ファイル名を外部キーの用語として他のテーブルに格納した場合でも、クラスター化インデックスキーが狭いため、これはより良い場合があります。ただし、この例は、これを行わない場合に適しています。

設計に、関連するデータを識別するための不便な主キーを含むデータのテーブルのインポートが含まれている場合は、ほとんどそれで行き詰まっています。

https://www.techopedia.com/definition/5547/primary-key は、すべてのデータテーブルで、顧客の社会保障番号を顧客キーとしてデータを保存するかどうかを選択する例を示しています。登録時に任意のcustomer_idを生成します。実際、これは、SSNが機能するかどうかは別として、SSNの重大な乱用です。これは個人的な機密データの価値です。

したがって、キーとして実際の事実を使用する利点は、「Customer」テーブルに再度参加しなくても、他のテーブルでそれらに関する情報を取得できることですが、これはデータセキュリティの問題でもあります。

また、SSNまたはその他のデータキーが誤って記録されていると問題が発生するため、「顧客」のみではなく、20の制約付きテーブルに誤った値が含まれています。一方、合成のcustomer_idには外部的な意味がないため、間違った値になることはありません。

3
Robert Carnegie