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

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

I realised after implementing the sync engine on the server side that this leads to performance issues when needing to map between uuid<->id all the time (when writing objects, I need to query for the uuid to get the id before saving and the opposite when sending back data).

我现在正在考虑切换到只使用UUID作为主键,从而使书写和阅读更简单、更快.

我已经读到,当使用聚集主键索引时,UUID作为主键有时会带来糟糕的索引性能(索引碎片).PostgreSQL会遇到这个问题吗?还是可以使用UUID作为主键?

我今天已经有了一个UUID列,所以在存储方面会更好,因为我删除了常规id列.

推荐答案

(我在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.(话虽如此,我还是希望听到有人在这种方法上遇到问题!)

Ruby-on-rails相关问答推荐

在Rails中,如何将帮助器方法添加到属性/列?

Rails - Comment.count没有改变1

Rails 控制台 - 更新 Gem 后的弃用通知

'elseif' 还存在吗?

Rails 中的转义值(类似于 mysql_real_escape_string())

如何在 Ruby on Rails 中创建一个锚点并重定向到这个特定的锚点

如何添加到序列化数组

SQLite3::BusyException

如何避免 has_many :through 关系中的重复?

没有要加载的文件 - readline

Ruby如何写入Tempfile

如何找出现有 Rails 应用程序基于哪个 Rails 版本?

Ruby on Rails 错误无法加载此类文件 - 更少

关闭 Firefox 中文本字段的自动完成功能

在 factory_girl 中填充与 children 的关联

Rails Activeadmin - 自定义关联 Select 框

如何为 Rails 迁移定义布尔字段

如何在 Rails 4 中测试控制器关注点

ActionMailer 在开发 Rails 4 中不发送邮件

如何为 Rails 控制器添加延迟以进行测试?