69

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

它有几个表,旨在能够与可以在不同位置创建数据的移动设备同步。因此,我有一个 uuid 字段,它是一个字符串,除了一个自动增量主键外,还存储一个 GUID。uuid 是服务器和客户端之间通信的一个。

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

我现在正在考虑切换到仅使用 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)

编辑性能影响

这将始终取决于您的工作量。

整数主键具有局部性优势,其中相似数据更靠近。这可能有助于例如:范围类型查询,例如WHERE id between 1 and 10000虽然锁争用更糟。

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

你在这张桌子上写了很多,这张桌子很大吗?尽管我没有对此进行测量,但有可能维持该指数会产生影响。不过,对于很多数据集,UUID 就可以了,并且使用 UUID 作为标识符具有一些不错的属性。

最后,我可能不是最有资格对此进行讨论或提出建议的人,因为我从来没有运行过一个足够大的表,它的 UUID PK 已经成为问题。YMMV。(话虽如此,我很想听听有人遇到这种方法的问题!)

于 2012-10-30T19:54:28.323 回答
3

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

自动增量自然按日期排序,因此当使用自动增量时,数据按时间顺序存储在磁盘上(请参阅 B-Tree),从而加快读取速度(无需寻找 HDD)。例如,如果列出所有用户,自然顺序将是按创建日期创建的,这与自动增量相同,因此范围查询在 HDD 上执行得更快,而在 SSD 上,我猜,差异将不存在,因为 SSD 设计上总是随机的访问(不寻头,不涉及机械部件,纯电)

于 2016-08-23T15:33:16.340 回答