データベース全体で単一のプライマリキーシーケンスを共有していますか?


14

すべてのテーブルで単一のシーケンスを主キーとして使用することは受け入れられる慣行ですか?その場合、テーブル全体で単一の主キーシーケンスを使用するよりも客観的に優れていますか。

私はDBAではなく、ジュニアソフトウェア開発者なので、優れたデータベース設計の基本の多くをまだ学んでいます。

編集:誰かが疑問に思っている場合、私は最近、私たちのデータベース管理者の1人によるデータベース設計の批判を読みました。私はこれまでに学びました。

編集2:コメントの質問に答えるために、これはOracle 11g用ですが、データベース固有ではないレベルで疑問に思っていました。この質問がデータベースに依存する場合、その理由を知りたいと思いますが、そのような場合、Oracleに固有の回答を探しています。


2
パフォーマンス上の理由から、これは通常ひどい考えです。
フィリ

1
実際には、各テーブルに独自の独立した主キー範囲を持たせると、より大きな利点があります。しかし、あなたが言うことができるIDの束を見るとき、これはアカウントであり、その1つはPurchaseHeaderなどです。これを行うには、いくつかのセットアップと(特別な目的のような)継続的なケアと給餌が必要です。(はい、私は何年も前にこのようなシステムで作業しました。)
RLF

どのDBMSを使用していますか?オラクル?Postgres?DB2?
a_horse_with_no_name

1
彼の言っていることを間違って解釈した可能性はありますか?たぶん彼はその通りではなかったのでしょうか?
ジェームズライアン

会社のDBAは、実際にはどのテーブルにも主キーフィールドがないことを意味していましたか?
マックスヴァーノン

回答:


13

許容できる?承知しました。一般?いいえ、有益ですか?疑わしい。

私の以前の仕事では、中央シーケンスジェネレーターを備えたシステムを継承しました(これは、SEQUENCESQL Server 2012で導入されるずっと前のSQL Serverシステムでした)。これは実際にはパフォーマンスのボトルネックではなく、毎秒数十万もの値を生成している場合を除きます。しかし、それはすべてのコードを必要以上に複雑にしました、正当な理由はありません。設計の意図は、システム内の何かに12のID値が割り当てられている場合、システム内の1つのものだけがID 12を持つことができるようにすることでした。CustomerID = 12の顧客がいる場合、OrderID = 12の注文ができないのはなぜですか?

複数のシステムがあり、これらの複数のシステムから特定の種類のエンティティ(顧客や注文など)のIDを生成している場合、中央シーケンスジェネレーターの有用性がわかります。中央シーケンスは、ボトルネック(単一障害点)になることなく、2つのシステムが同じIDを生成することを恐れることなく、複数のシステムに新しい値を与えることができます。


このようなものと、主キーとしてuniqueidentifiersを使用するもののいずれかを選択する必要がある場合は、好みがあります(答えは「依存する可能性が高い」)。GUIDは、同じ方法で問題を回避するように見えますが、独自の集中化された主キージェネレーターをロールする必要はなく、標準の実装を取得します。明らかに、SQL 2012でシーケンスを使用すると両方のことを達成できますが、誰かが古いバージョンを使用していると想定していますか?
SqlRyan

2
@SqlRyan OrderIDがCustomerIDと完全に区別される必要がある理由を理解する必要があります。私はほとんど確実にこれにGUIDを使用しません。IDENTITY範囲を設定する方が良い場合があります(顧客が1で始まり、注文が1000000で始まるなど)。もちろん、範囲を使い果たしそうになったときにアラートを設定します。
アーロンバートランド

1
@SqlRyan-クラスタ化された主キーとして実装が不十分なGUIDを使用すると、あらゆる種類の問題が発生する可能性があります。アーロンが言ったように、IDENTITYははるかに目的に合っています。
マックスヴァーノン

以前のシステムでは、データベース全体で単一のシーケンスを使用していましたが、これは単一のテーブルではなく多数の異なるテーブルを外部キーが指すようにするために行われたため、2つの異なる行の外部キー12歳だったので、彼らは彼らが指している可能性のあるテーブルをチェックする必要なしに同じものを指していることを知っていました。同じ列の13は、別のテーブルの主キーになる可能性があります。私はそのデザインスタイルに個人的に非常に不快です。
ロートンフォーグル

@AaronBertrandまたは、単純な整数の識別子を使用し、これらが顧客向けの場合、先頭にコードを追加します。例えば。I1337、C1337は明らかに請求書または顧客
JamesRyan

7

この考え方は、INT IDが同じであるという理由だけで、間違った列を使用して誤ってテーブルに参加し、無効な行を取得する可能性がある非常に複雑なデータベースにメリットがあります。

GUIDのインデックスフラグメンテーションの落とし穴のいくつかを回避するために、プライマリキーとしてシーケンシャルGUIDを選択しました。悲しいことに、それらは非常に大きいです。

SQL Serverは、デフォルトでnewSequentialID()関数を呼び出すことでシーケンシャルGUIDを生成できるため、発行するキーのテーブルを維持したり、ブロッキングのボトルネックをなくしたりできます。

これにより、データベース全体で、実際には企業全体で一意のIDが付与されました。

もちろん、価格はスペースであり、データをより小さな整数キーを使用することで速度/サイズが予測されるデータウェアハウス/キューブにデータを渡そうとすると問題になります。

私たちはそれらを使用した結果として、アプリの多くのバグを回避したと確信しています。


4

すべてのテーブルにわたる単一のシーケンスの背後にある理由が何であるか想像できません。新しい値を生成するときにボトルネックを作成するだけです。

順次キー値を生成するオーバーヘッドがどれほど小さくても、ジェネレーターは単一のリソースであり、そのリソースへのアクセスは同期する必要があります。取得するリクエストが多いほど、一部のリクエスタがタップで順番を待つ必要が生じる可能性が高くなります。すべてのテーブル間で共有される単一のシーケンスジェネレーターは、複数のジェネレーターのいずれよりも多くのクライアントによって頻繁にアクセスされるため、より多くの競合が発生することは明らかです。ギャップや厳密な順序付けがない、クラスター化されたデータベースなど、ビジネスルールが生成された値に制約を課すと、競合がより顕著になる可能性があります。

最も効率的なシーケンスジェネレータを使用しても、許容できない競合を引き起こすワークロードが発生します。


2
ボトルネックがどのように作成されるか、なぜそれが悪い考えであるかについての詳細を追加することができます。
マックスヴァーノン

2

データベーステーブルのPrimaryKeyの目的は、主に、一意であると想定されるデータの一意性を強制することです。これは、すべてのワークフローをカバーできず、データの重複が発生しないことを保証できないためです。2番目の理由は、多くの場合、PKはテーブルのクラスター化インデックスの主要な候補でもあるため、これらの列が選択クエリで適切に使用されるとき/場所でデータの取得を促進するためです。

主キーとしてシーケンス番号を使用することは、すべてのテーブルにIdentity列があり、その列のみがPrimaryKeyで使用されていることと同じです。DB全体で単一のシーケンス番号を使用するには、特定の使用方法が必要ですが、PrimaryKeyの観点からは理由がわかりません。たとえば、私が取り組んだDatawarehouseプロジェクトの1つでは、LoadBatchIDと呼ばれる列があり、ETLからすべてのテーブルの50%がこの列を持っていますが、場所によっては意味が異なります。一意のprocを番号ジェネレーターとして使用して、競合を見つけないようにし、ETLの各段階で発生したデータと元のファイルから元のファイルにトレースバックできるようにしました。


2

すべてのエンティティが親エンティティから継承された場合、それを行う理由の1つだと思います。たとえば、任意のタイプのエンティティにコメントを追加できるようにしたいとします。

create table god_entity (
  id bigserial primary key
);

create table some_table (
  id bigint primary key references god_entity(id),
  ...
);

create table some_other_table (
  id bigint primary key references god_entity(id),
  ...
);

create table comment (
  id bigint primary key references god_entity(id),
  ...
);

create table entity_comment (
  entity_id bigint not null references god_entity(id),
  comment_id bigint not null references god_entity(id),

  primary key (entity_id, comment_id)
);

通常、これは行われません。。

パフォーマンス特性については知りません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.