69

Rails on Heroku で PostgreSQL データベースを使用してアプリを作成しました。

さまざまな場所でデータを作成できるモバイル デバイスと同期できるように設計されたテーブルがいくつかあります。そのため、自動インクリメントの主キーに加えて、GUID を格納する文字列である uuid フィールドがあります。uuid は、サーバーとクライアントの間で通信されるものです。

サーバー側に同期エンジンを実装した後、常に uuid<->id 間でマップする必要がある場合にパフォーマンスの問題が発生することに気付きました (オブジェクトを書き込むときは、保存する前に ID を取得するために uuid を照会する必要があり、データを送り返すときは逆)。

現在、UUID のみを主キーとして使用するように切り替えて、書き込みと読み取りをより簡単かつ高速にすることを考えています。

UUID を主キーとして使用すると、クラスター化された主キー インデックスを使用すると、インデックスのパフォーマンスが低下することがあります (インデックスの断片化)。PostgreSQL はこの問題に悩まされていますか、それとも UUID を主キーとして使用しても問題ありませんか?

今日はすでに UUID 列を持っているので、通常の id 列を削除するため、ストレージの観点からはより良いでしょう。

4

2 に答える 2

66

(私は Heroku Postgres で作業しています)

いくつかのシステムでUUIDを主キーとして使用していますが、うまく機能しています。

拡張機能を使用することをお勧めしますuuid-ossp。また、postgres に UUID を生成させることもお勧めします。

heroku pg:psql
psql (9.1.4, server 9.1.6)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.

dcvgo3fvfmbl44=> CREATE EXTENSION "uuid-ossp"; 
CREATE EXTENSION  
dcvgo3fvfmbl44=> CREATE TABLE test (id uuid primary key default uuid_generate_v4(), name text);  
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"
CREATE TABLE  
dcvgo3fvfmbl44=> \d test
                 Table "public.test"  
Column | Type |              Modifiers              
--------+------+-------------------------------------  
id     | uuid | not null default uuid_generate_v4()  name   | text |  
Indexes:
    "test_pkey" PRIMARY KEY, btree (id)

dcvgo3fvfmbl44=> insert into test (name) values ('hgmnz'); 
INSERT 0 1 
dcvgo3fvfmbl44=> select * from test;
                  id                  | name  
--------------------------------------+-------   
 e535d271-91be-4291-832f-f7883a2d374f | hgmnz  
(1 row)

EDIT パフォーマンスへの影響

それは常にあなたのワークロードに依存します。

整数の主キーには、類似データがより近くに位置するという局所性の利点があります。WHERE id between 1 and 10000これは、たとえば、ロックの競合が悪化するなどの範囲タイプのクエリに役立ちます。

読み取りワークロードが完全にランダムであり、常に主キーのルックアップを行う場合、測定可能なパフォーマンスの低下はありません。より大きなデータ型に対してのみ料金が発生します。

このテーブルにたくさん書き込みますか? このテーブルは非常に大きいですか? 私はこれを測定していませんが、その指標を維持することに意味がある可能性があります。ただし、多くのデータセットでは UUID で問題ありません。UUID を識別子として使用すると、いくつかの優れた特性があります。

最後に、私はこれについて議論したりアドバイスしたりするのに最も適した人物ではないかもしれません.UUID PKで十分な大きさのテーブルを実行したことがなく、それが問題になったことはありません. YMMV。(そうは言っても、アプローチで問題に遭遇した人の話を聞きたいです!)

于 2012-10-30T19:54:28.323 に答える
3

受け入れられた回答が述べているように、この場合、範囲クエリは遅くなる可能性がありますが、id.

自動インクリメントは当然日付でソートされるため、自動インクリメントを使用すると、データは時系列でディスクに保存され (B ツリーを参照)、読み取りが高速化されます (HDD のシークは不要)。たとえば、すべてのユーザーをリストする場合、自動インクリメントと同じように作成日順で自然な順序になるため、範囲クエリは SSD では HDD でより高速に実行されます。SSD は設計上常にランダムであるため、違いは存在しないと思います。アクセス(ヘッドシークなし、機械部品なし、純粋な電気のみ)

于 2016-08-23T15:33:16.340 に答える