web-dev-qa-db-ja.com

データベースの主キーのUUID、自動インクリメント/シーケンスキー、シーケンステーブルから選択するにはどうすればよいですか?

私は、データベース行の主キーを考え出すこれらの3つの主要な方法の長所と短所を見ています。

したがって、これらのメソッドを複数サポートするデータベースを使用していると仮定すると、最適なオプションを決定するための簡単なヒューリスティックはありますか?

分散/複数のマスター、パフォーマンス要件、ORMの使用、セキュリティ、テストなどの考慮事項は、どのように選択するのですか?

遭遇する可能性のある予期しない欠点はありますか?

32
Tim

UUID

これらが「単調な順序で」生成されない限り、インデックスを大幅に傷つけたり断片化したりする可能性があります。 UUID生成のサポートは、システムによって異なります。使用可能ですが、ほとんどの場合、UUIDをプライマリクラスターインデックス/ PKとして使用しません。必要に応じて、おそらくインデックス付きのセカンダリ列にしますが、そうでない場合もあります。

UUIDを使用して、任意の数のシステムからレコードを安全に生成/マージできると主張する人もいます。 UUID(メソッドによって異なります)は一般に、天文学的に衝突の可能性が低いですが、少なくとも外部入力がある場合、またはvery不運:)-衝突を生成する可能性があります。私は、true PKのみがシステム間で送信されるべきであり、ほとんどの場合、データベース生成 UUIDではないと主張します(または送信されるべきではない)と信じています。 。

自動インクリメント/シーケンスキーとシーケンステーブル

これは、データベースが何を適切にサポートしているかによって異なります。一部のデータベースは、単純な「自動インクリメント」よりも柔軟なシーケンスをサポートしています。これは望ましい場合と望ましくない場合があります(または、この種のタスクを単純に行う唯一の方法である場合もあります)。シーケンステーブルは一般的にはまだ柔軟性がありますが、この種の「柔軟性」が必要な場合、特にトリガーの使用を伴う場合は、戻ってデザインパターンにアクセスしたくなるでしょう。 「ORMの制限」は嫌いですが、「より単純な」自動インクリメントまたはシーケンスタイプ/データベースサポートの選択にも違いが生じる可能性があります。

使用する方法に関係なく、代理主キーを使用する場合は、真の主キーを識別し、スキーマにエンコードする必要があります。

さらに、「自動シーケンスPKを公開することによるセキュリティの侵害」は、internalデータベースプロパティを誤って公開した結果であると私は主張します。 CRUD操作を処理する非常に簡単な方法ですが、内部キー公開キー(例:かなりの顧客番号)には違いがあると思います。

ちょうど私の2セント。

編集、ティムへの追加の返信:

生成されたPKと真のPKの質問は非常に優れたものであり、私も考慮する必要があると思います。私はあなたが言うポイントに一般的にUUIDが欲しいです。私の躊躇はサイズ対int/longでした。私にとってはるかに大きな懸念である潜在的なインデックスの最適化解除に気づいていませんでした。

サイズについてはあまり気にしません。UUIDが最適な場合は、それが最適です。そうでない場合は、そうではありません。 全体的なスキーム intを超える12バイトの追加は、ほとんど違いがない可能性があります。 SQL Server 2005+は、通常のUUID生成に関連する断片化を回避するために、 newsequentialid UUID生成関数をサポートしています。このページでは、それについていくつか説明しています。他のデータベースにも同様のソリューションがあると確信しています。

また、「スキーマにエンコード」とは、一意性の制約を追加するだけではありませんか?

はい。主キーが唯一の[一意の]制約である必要はありません。サロゲートPKを使用するだけでは、データベースモデルが危険にさらされる必要があるという意味ではありません:-)追加のインデックスを使用してカバーすることもできます。

そして、「の区別」によって、代理の主キーが決して漏れないということですか?

私の最初の投稿の言葉遣いは少し難しいものでした。それは「もしそうならそしてそれが重要ならそれは別の問題だ」ほど「決して」ではない。多くの場合、人々は推測可能な数によって不安を訴えます-例:ご注文が23の場合、注文22や24などが発生する可能性があります。これが「保護」であるか、機密情報が漏洩する可能性がある場合は、システムにすでに欠陥があります。 (内部IDと外部IDを分離しても本質的にこの問題は修正されず、認証/承認は引き続き必要です。ただし、「シーケンシャルID」の使用に対して発生する問題の1つです。ナンスを分散URLにエンコードすると、これが処理されますfor myユースケースはかなりうまくいきます。)

私の詳細本当に知りたかった:代理PK IDが8942であるからといって、それが8942の順序であるとは限りません。つまり、「一部のフィールドはdbの内部にのみ存在します。 「設計、注文「番号」は、「#2010-42c」やビジネス要件に適したものなど、表面上はまったく関係がない場合があります(ただし、DBモデルでは完全にサポートされています)。ほとんどの場合に公開されるのは、このexternal番号です。

他のフィールドは変更可能であるため、生成されたキーが実際には真の主キーである場合があると感じます(たとえば、ユーザーが電子メールとユーザー名を変更する場合があります)。

これは事実かもしれませんwithinデータベースであり、私はこのステートメントについて議論しません。ただし、サロゲートPKはデータベースに対してinternalであるともう一度考えて、十分に識別できるタプルのみをエクスポート/インポートするようにしてください。ユーザー名/電子メールが変更される可能性がある場合、これにはアカウントの作成時に割り当てられたUUIDが含まれている可能性があり、代理PK自体である可能性があります。

もちろん、すべての場合と同様に、開いたままにして、モデルの問題ではなく、問題にモデルを適合させます:-)たとえば、Twitterのようなサービスの場合、独自の番号生成スキーマを使用します。 Twitterの新しいID生成 を参照してください。 [一部の] UUID生成とは異なり、Twitterによるアプローチ(すべてのサーバーが正しくセットアップされていることを前提とします)保証分散マシン/プロセスのいずれも重複IDを生成せず、64ビットのみを必要とします。大まかな順序を維持します(最も重要なビットはタイムスタンプです)。 (Twitterによって生成されるレコードの数は、地域の要件とはまったく関係がない場合があります;-)

ハッピーコーディング。

30
user166390