すべてのテーブルで単一のシーケンスを主キーとして使用することは許容できますか(主キーは特定のテーブルで一意ではなく、すべてのテーブルで一意です)?その場合、テーブル間で単一の主キーシーケンスを使用するよりも客観的に優れていますか。
私はDBAではなくジュニアソフトウェア開発者なので、優れたデータベース設計の基本の多くをまだ学んでいます。
編集:誰かが不思議に思っている場合、私は最近、設計がデータベース全体で単一の主キーを使用していないことが問題であると述べた当社のDBAの1人によるデータベース設計の批評を読みました。私はこれまでに学びました。
Edit2:コメントの質問に答えるために、これはOracle 11g向けですが、データベース固有ではないレベルで疑問に思っていました。この質問がデータベースに依存している場合、その理由を知りたいのですが、そのような場合は、Oracleに固有の回答を探します。
受け入れられる?承知しました。一般?いいえ。有益ですか?疑わしい。
私の古い仕事では、中央シーケンスジェネレーターを備えたシステムを継承しました(これは、SQL Server 2012でSEQUENCE
が導入されるずっと前のSQL Serverシステムです)。これは実際にはパフォーマンスのボトルネックではなく、毎秒数十万の値を生成している場合を除いて、ボトルネックになることはありません。しかし、正当な理由もなく、すべてのコードが必要以上に複雑になりました。この設計の目的は、システム内の何かにID値12が割り当てられている場合、システム内の1つだけがID 12を持つことができることを確認することでした。 CustomerID = 12の顧客がいる場合、なぜそれによってOrderID = 12の注文ができなくなるのですか?
複数のシステムがあり、これらの複数のシステムから特定の種類のエンティティ(たとえば、顧客または注文)のIDを生成している場合は、中央シーケンスジェネレーターの有用性がわかります。中央のシーケンスは、ボトルネック(単なる単一障害点)になることなく、2つのシステムが同じIDを生成することを心配することなく、新しい値を複数のシステムに分配できます。
INT IDが同じであるという理由だけで、誤った列を使用してテーブルに誤って結合し、無効な行を取得する可能性がある非常に複雑なデータベースでは、このアイデアにメリットがあります。
GUIDのインデックスの断片化の落とし穴のいくつかを回避するために、主キーとして連続したGUIDを選択しました。悲しいことに、それらはかなり大きいです。
SQLサーバーは、newSequentialID()関数を呼び出すデフォルトで順次GUIDを生成できるため、発行するキーのテーブルを維持したり、ブロッキングのボトルネックを発生させたりすることがありません。
これにより、データベース全体、企業全体で一意のIDが実際に一意になっているため、IDを取得できました。
もちろん、価格はスペースであり、データをデータウェアハウス/キューブに転送しようとするときに問題が発生します。データウェアハウス/キューブでは、速度/サイズが小さい整数キーの使用に基づいています。
私たちはそれらを使用した結果として、アプリの多くのバグを回避したと確信しています。
すべてのテーブルにわたる単一のシーケンスの背後にある理由が何であるかは想像できません。新しい値を生成するときにボトルネックが発生するだけです。
シーケンシャルキー値を生成するオーバーヘッドがどれほど小さい場合でも、ジェネレーターは単一のリソースであり、アクセスを同期する必要があります。リクエストが多いほど、一部のリクエスターがタップで順番を待つ必要が生じる可能性が高くなります。すべてのテーブル間で共有される単一のシーケンスジェネレーターは、複数のジェネレーターのどれよりも、より多くのクライアントからより頻繁にアクセスされるため、より多くの競合が発生します。ビジネスルールが、ギャップの欠如や厳密な順序付けなどの生成された値、またはクラスター化されたデータベースに制約を課す場合、競合はより顕著になる可能性があります。
そこに最も効率的なシーケンスジェネレータがあってもされる許容できない競合を引き起こすワークロード。
データベーステーブルのPrimaryKeyの目的は、すべてのワークフローをカバーできず、データの重複が発生しないことを保証できないため、主に一意であると想定されるデータの一意性を適用することです。 2番目の理由は、多くの場合、PKはテーブル上のクラスター化インデックスの主要な候補でもあるため、これらの列が選択クエリで適切に使用されている場合や場所でデータの取得が高速化されることです。
シーケンス番号を主キーとして使用することは、すべてのテーブルにIdentity列があり、その列のみがPrimaryKeyで使用されているのと同じです。 DB全体で単一のシーケンス番号を使用するには、特定の使用法が必要ですが、PrimaryKeyの観点からは理由がわかりません。たとえば、私が取り組んだDatawarehouseプロジェクトの1つでは、LoadBatchIDという列があり、ETLからレポートまで、すべてのテーブルの50%にこの列がありますが、場所によっては意味が異なります。一意のprocを数値ジェネレーターとして使用して、競合が検出されないようにし、データの取得元の元のファイルに戻って、ETLのさまざまな段階で何が起こっているかを追跡できるようにしました。
これを行う理由の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)
);
通常、これは行われません。 。
パフォーマンス特性についてはわかりません。