将UUID作为PostgreSQL中的主键会给索引性能带来不好的影响吗?

我使用PostgreSQL数据库在Heroku上的Rails中创build了一个应用程序。

它有两个表,旨在能够与移动设备同步数据可以在不同的地方创build。 因此,我有一个uuid字段,除了一个自动递增主键之外,它还是一个存储GUID的string。 uuid是在服务器和客户端之间进行通信的。

我意识到在服务器端实现同步引擎后,当需要在uuid < – > id之间进行映射的时候,会导致性能问题(编写对象时,我需要在保存之前查询uuid以获取id,发送回数据时相反)。

我现在考虑切换到只使用UUID作为主键,使写和读更简单,更快。

我读过UUID作为主键,有时在使用集群主键索引时可能会导致错误的索引性能(索引碎片)。 PostgreSQL会遇到这个问题,还是可以使用UUID作为主键?

我今天已经有一个UUID列,所以存储方面会更好,因为我放弃了常规ID列。

(我在Heroku Postgres上工作)

我们在一些系统上使用UUID作为主键,它工作的很好。

我build议你使用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) 

编辑性能影响

这将总是取决于你的工作量。

整数主键具有类似数据位置相近的地方的优点。 这对于例如范围types的查询是有帮助的,例如WHERE id between 1 and 10000尽pipe锁争用更糟糕。

如果您的读取工作负载是完全随机的,那么您总是进行主键查找,不应该有任何可衡量的性能下降:您只需支付更大的数据types。

你写了很多这张桌子,这张桌子很大吗? 尽pipe我没有衡量这一点,但有可能在维持这一指数方面有所影响。 对于大量的数据集,UUID虽然很好,但使用UUID作为标识符有一些很好的属性。

最后,我可能不是最合适的人讨论或build议,因为我从来没有运行一个足够大的UUID PK表,它已成为一个问题。 因人而异。 (话虽如此,我很想听听那些遇到问题的人!)

正如接受的答案所述,范围查询在这种情况下可能会很慢,但不仅仅是id

自动增量按date自然sorting,所以当使用自动增量时,数据按时间顺序存储在磁盘上(请参阅B-Tree),以加快读取速度(不需要寻找硬盘驱动器)。 例如,如果列出所有用户,自然顺序将按创build的date创build,这与自动增量相同,所以在SSD上执行范围查询的速度更快,但我猜测,由于SSD的devise总是随机的接入(无需求头,不涉及机械部件,只需纯电力)