2012-10-30 53 views
50

私は、PostgreSQLデータベースを使用してHerokuのRailsにアプリケーションを作成しました。PostgreSQLのUUIDは主キーとして索引のパフォーマンスが悪いですか?

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

サーバー側で同期エンジンを実装した後で、これはパフォーマンス上の問題につながります。これは、uuid < - > idの間で常にマッピングする必要があるときです(オブジェクトを書き込むときには、保存する前に、データを送り返すときは反対に)。

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

クラスタ化された主キー索引を使用すると、主キーとしてUUIDが悪いインデックスのパフォーマンス(インデックスの断片化)を示すことがあります。 PostgreSQLはこの問題を抱えていますか、またはUUIDを主キーとして使用できますか?

私はすでに今日のUUID列を持っていますので、私は通常のID列を削除するので、ストレージが賢明です。

+2

'id'フィールドはデータベース内の他のリレーションによって外部キーとして使用されていますか?あなたが説明した理由でプライマリキーがシリアルタイプでなければならないと信じているので、この「id」フィールドだけを守っていますか? –

+0

合成プライマリ・キーによるクラスタリングは、これらのpkey値の範囲を問い合せる頻繁なアクセス・パスを持つ場合にのみ有益です。これは現実世界ではまれです。 UUIDは主キーの完全に細かい型です。テキスト型と比較して十分にコンパクトで(16バイト)高速です。 – dbenhur

+0

@Joshua IDフィールドは外部キーとして使用され、UUIDフィールドは通信時に関係を参照するのに使用される通常のフィールドとしてのみ使用されます(常にそれらの間で変換する必要があります) – thejaz

答えて

55

(私は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のパフォーマンスへの影響

をそれは常にはワークロードに依存します。

整数の主キーには、like-dataが近くに位置するローカリティの利点があります。これは例えば:WHERE id between 1 and 10000のような範囲型のクエリに役立ちますが、ロックの競合は悪化します。

読んでいるワークロードが完全にランダムで、常に主キーの参照を行う場合は、測定可能なパフォーマンスの低下はないはずです。

あなたはこのテーブルに多くを書きますか?このテーブルは非常に大きいですか?私はこれを測定していませんが、その指数を維持することには意味があります。多くのデータセットでは、UUIDはうまくいきます.UUIDを識別子として使用すると、いくつかの素敵なプロパティがあります。

最後に、これについて議論したり助言を与える資格のある人ではないかもしれません。問題が発生したUUID PKで十分な大きさのテーブルを実行したことはありません。 YMMV。 (このアプローチで問題に遭遇した人のことを聞きたいのですが)

+0

お返事ありがとうございます。私は今日のRailsモデルでUUIDを作成していますが、これは上記のデータベース関数を使用するのと同じくらい良いのですか? – thejaz

+0

はい、あなたのレールモデルがデータベースにデータを挿入する唯一のものであれば問題ありません。 – hgmnz

+0

@hgmnz:Railsの移行を介してid列をUuidに定義するにはどうすればよいですか? –

1

この場合、範囲クエリは遅いかもしれませんが、idだけではありません。

自動インクリメントは日付によってソートされるため、オートインクリメントを使用すると、データはディスク上に時系列で格納されます(B-Tree参照)。たとえば、すべてのユーザーがリストされていれば、オートインクリメントと同じ日付けで自然順序が作成されるため、SSD上では範囲照会がHDD上でより高速に実行されます。SSDは常にランダムであるため違いはありません

関連する問題