将UUID作为PostgreSQL的主键会给出糟糕的索引性能吗?

时间:2012-10-30 19:05:50

标签: ruby-on-rails ruby postgresql heroku

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

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

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

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

我已经读过,当使用聚簇主键索引时,UUID作为主键有时会导致错误的索引性能(索引碎片)。 PostgreSQL是否遇到此问题,或者将UUID用作主键是否可以?

我今天已经有了一个UUID列,因此存储方式会更好,因为我删除了常规id列。

2 个答案:

答案 0 :(得分:56)

(我在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来运行足够大的表,因为它已经成为一个问题。因人而异。 (话虽如此,我很想听到那些遇到问题的人!)

答案 1 :(得分:1)

As the accepted answer states, range queries may be slow in this case, but not only on id.

Autoincrement is naturally sorted by date, so when autoincrement is used the data is stored chronologically on disk (see B-Tree) which speeds up reads (no seeking for HDDs). For example, if one lists all the users the natural order would be by date created which is the same as autoincrement and so range queries execute faster on HDDs while on SSD, i guess, the difference would be nonexistent since SSDs are by design always random access (no head seeking, no mechanical parts involved, just pure electricity)