UUIDまたはGUIDを主キーとして使用する場合の欠点は何ですか?


60

分散システムを構築したいと思います。データベースにデータを保存する必要がありますが、一部のテーブルの主キーとしてUUIDまたはGUIDを使用すると便利です。UUID / GUIDは非常に大きく、ほとんどランダムであるため、この設計の欠点だと思います。別の方法は、自動インクリメントのINTまたはLONG​​を使用することです。

テーブルの主キーとしてUUIDまたはGUIDを使用することの欠点は何ですか?

おそらく、DBMSとしてDerby / JavaDB(クライアント上)とPostgreSQL(サーバー上)を使用します。


なぜ役立つのでしょうか?あなたが最も重視している欠点は何ですか?このあいまいなすべてのDB質問に対する答えは、「依存します」です。詳細を教えてください。読み取りまたは書き込みのパフォーマンスに最も興味がありますか?どのレベルの分布について話しているのですか?
ブライアンボールサンスタントン

@Brian:分散システムのUUIDは、クライアントで主キーを作成し、データを非同期でサーバーにアップロードできるため便利です。私は主に読み取りパフォーマンスの欠点について考えています。UUIDで多くのJOINを使用するのは、おそらく良いことではありませんか?例では、クライアントがアイテム(UUID、名前、サプライヤ、作成者)をインベントリシステムに追加すると、ローカルデータベースがサーバー上の中央データベースと同期されます。
ジョナス

1
これに関するコメントをさらに明確にすることなく、せいぜい「依存する」ことになると思います。それらがなければ、私はVtCに行きます。
jcolebrand

GUIDと非GUIDがSQL Serverのクラスター化インデックスに与える影響について説明している記事があります。別のSQL製品に関連していても興味深いことがあります。x.co/ Twpp
Jeff

DerbyのドキュメントにはUUIDがデータ型としてリストされていないことに気付きました。UUIDデータ型をリストする H2 Database Engine(Derbyのような純粋なJavaデータベース)などの代替手段を検討することをお勧めします。もちろん、Postgresは、UUID値の効率的な保存、インデックス付け、および生成をサポートしています。
バジルブルク

回答:


29

生成関数とファイナルテーブルのサイズに依存します

GUIDは、グローバルに一意の識別子であることが意図されています。Postgres 8.3のドキュメントで説明されているように、これらの識別子を生成するのに普遍的に適切な方法論はありませんが、postgreSQLにはさらに有用な候補がいくつかあります。

問題の範囲とオフラインでの書き込みの必要性から、GUID以外の使用は完全にボックス化されているため、他のスキームの代償的な利点はありません。

機能的な観点から、キーの長さは通常、読み取りの数とテーブルのサイズに応じて、現代のシステムでは問題になりません。別の方法として、オフラインクライアントはプライマリキーなしで新しいレコードバッチ処理し、再接続時に単純に挿入できます。postgreSQLは「シリアル」データ型を提供するため、クライアントがデータベースへの単純な書き込みを実行できる場合、IDを決定する必要はありません。


3
くそー、寝てブライアンに質問に答えさせた。はい、「オフライン更新」の要件により、そこでの概念全体が完全に変更されました。
jcolebrand

ムアハハハア!::ひどく口ひげを
くるくる

1
オフライン書き込みでも、INTを使用できます。たとえば{Node_ID, Item_ID}、各ノードにがありNode_ID、ノードごとにItem_ID自動インクリメントされる2つの列を使用します。
ジョナス

@Jonas〜はい、可能です。ただし、ほとんどの人がGUIDを考えている理由の 1つは、コンテンツを他のデータベースにグローバルに分離して複製するためです。つまり、用語自体はむしろQEDです。
jcolebrand

マスター/スレーブアーキテクチャまたはスパース接続クライアント+メインサーバーアーキテクチャに関しては、マスターでglobal_id(SERIAL)を使用し、スレーブでglobal_id(BIGINT)+ local_id(SERIAL)を使用することが可能です。スレーブはlocal_idを使用してローカル作業を行い、マスターに向けてコミットするとコミットします。マスターはデータを受信し、スレーブに返すglobal_idを付与します。スレーブはglobal_idフィールドを更新します奴隷)。
ミハイスタンキュー

22

もう1つのアドバイス-クラスター化インデックスの一部としてGUIDを使用しないでください。GUIDはシーケンシャルではないため、クラスター化インデックスの一部である場合、新しいレコードを挿入するたびに、データベースはすべてのメモリページを再配置して適切な挿入場所を見つける必要があります(int(bigint)auto-incrementの場合)最後のページになります。

ここで、dbの実現に注目すると:1.)MySQL-プライマリキーはクラスタ化され、動作を変更するオプションはありません-推奨事項はここでGUIDをまったく使用しないことです2.)Postgres、MS-SQL-GUIDをプライマリキーはクラスタ化されていないため、別のフィールドをクラスタ化インデックスとして使用します(自動インクリメントintなど)。


Postgresに対して提案することは、わずかに異なる構造(auto_increment PK(クラスター化キー)、一意のインデックスを持つGUID(非クラスター化))を使用して、MySQLでも実行できます。
ypercubeᵀᴹ

これは必ずしも真実ではありません。ディスクシステムのスループットによっては、その最後のページへのアクセスの同期がボトルネックになる場合があります。blog.kejser.org/2011/10/05/…– mwilson 13
1

2
「Microsoft SQL Serverとは異なり、PostgreSQLのインデックスでのクラスタリングはその順序を維持しません。順序を維持するには、CLUSTERプロセスを再適用する必要があります。」どのようにCLUSTERのONは、インデックスのパフォーマンス向上しない
バルトロ-otrit

:情報の@バルトロ-otritにリンクされているのより要約版stackoverflow.com/a/4796685/1394393。この質問はPGに関するものであり、存在しないSQL ServerおよびMySQLとの類似性を想定しているため、この答えは本当に私には関係がないようです。
jpmc26

database would need to rearrange all its memory pages to find the right place for insertion=>クラスタリングはオプションであり、新しい行は順不同で格納されるため、Postgresの場合はそうではないと思います。
フラビエン

3

場合によります。

真剣に、あなたがこれまでに与えたすべてで、これはあなたが行くことができる限りである。

UUIDを使用すると便利なのはなぜですか?なぜINTを使用しないのですか?後でUUIDのインデックスを作成できないのはなぜですか?UUIDのキーを使用してソートされたリストを作成し、数百万行の後にランダム(非シーケンシャル)UUIDを挿入することの意味を理解していますか?

これはどのプラットフォームで実行されますか?ディスクはいくつですか?ユーザー数は?レコードはいくつですか?


7
コメントに書いたように、UUIDを使用すると、クライアントはサーバーに接続せずにデータベースに行を追加し、後でサーバーと同期できます。複数のクライアントが異なるアイテムに同じプライマリキーを使用する可能性があるため、プライマリキーにINTを使用する場合、それはできません。まあ、UUID列でリストを並べ替えるのは無意味です。タイムスタンプ列で並べ替える方が便利です。いいえ、数百万行の後にランダムな非順次UUIDを挿入することの意味がわかりません。そのため、この質問をします。
ジョナス

アプリケーションはJavaで記述され、クライアントはWindows、MacまたはLinuxを使用します。クライアントは、通常1つのディスクを持つ一般的なデスクトップコンピューターを使用します。ユーザーとレコードの数は、獲得する顧客の数によって異なりますが、クライアントと顧客ごとに約5000になります。
ジョナス

1
オフラインコメントはすべてを変えました。詳細は何を参照してください?
jcolebrand
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.