数据库 MySQL 用 UUID 作为主键,实际使用中有什么问题

kgen · 发布于 2015年03月06日 · 最后由 oxffff 回复于 2015年04月02日 · 19595 次阅读
370
本帖已被设为精华帖!

最近有一个产品尝试采用 UUID 代替默认的 int 主键。

由于没有在大规模的生产环境中这样用过,虽然搜索了关于 MySQL UUID 主键的优劣势文章,但毕竟案例还是太少,很多还停留在性能测试阶段。

论坛中是否有朋友在生产环境中采用过 ActiveRecord + MySQL UUID 主键的方案,有没有什么特别的坑?

共收到 30 条回复
896

还没在生产环境试过。不过看网上资料,主键的字段类型设置引起不同的性能变化 postgresql的uuid比text省空间 http://simononsoftware.com/how-to-store-uuids-in-postgresql/ SO上关于mysql的两篇文章 http://stackoverflow.com/questions/412341/how-should-i-store-guid-in-mysql-tables http://stackoverflow.com/questions/2365132/uuid-performance-in-mysql/2365176

370

#1楼 @foxzool 嗯,谢谢!这些文章我都看过,为了不干扰回答者的倾向性,所以我没有在主贴贴出来。主要还是想听听大家实践的成果。

14713

我的理解,UUID的优势就是天然适应高并发的环境下使用。如果id顺序递增,每创建一条记录都需要对表加一次锁,这在高并发环境下是很大的开销,有时候甚至是不能容忍的。

370

#3楼 @cuterxy 是的,在并行插入下,理论上 UUID 的确有优势。但是纯性能测试中,它的插入性能随着数据量指数级减慢。

14713

#4楼 @kgen 插入性能随数据量指数级减慢的原因是你只在单机上进行测试。而UUID可以无痛支持对表进行水平划分,将数据分布存储在多台不同的机器上。只要机器可以无限扩展,插入性能就能够得到保证。

1342

感觉应该没什么问题吧

96

新浪微博的主键采用的是自己设计的UUID算法。 参考 http://www.infoq.com/cn/articles/online-data-migration-experience

370

#5楼 @cuterxy 非常感谢指出单机测试的局限性,我们用分布式的环境再测一下。

370

#7楼 @vincent 嗯,UUID 索引变大和簇类索引引起数据位置频繁变动,的确是我们最担心的。 你们有没有小项目尝试过 UUID 做主键?

370

#8楼 @taomaree 赞,看了 id generator 的源码,原理都差不多,但是weibo的确根据自己的业务指标,搞了个最适合自己的。

332

#10楼 @kgen 我们还没有尝试过,:)

96

我们做过类似的处理,但不是UUID,是用redis产生id。因为我的程序需要高写入,所以先要生成内存中的缓存对象,然后再用异步程序进行处理。我不用UUID是因为会失去了时间顺序的排列,一些地方可以简单的根据id排序来得到时间序列。这在后端构造redis的zset时候有时候有很大的方便。

370

#13楼 @jimrokliu 借助 redis 生成 id 后,稍后写入主DB,的确是个好办法,感谢提供思路

15

像 twitter 那样搞就可以了

14174

刚发了个贴请教同样的问题,自己的小项目。 然后又搜到此贴,看了看回复,想了下,不如直接 MongoDB 算了~

17467

用UUID比较占地方,效率方面不同的数据库可能不一样,优点是比较独立,迁移不受影响。

15

看看 csdn 论坛 又换回来了

370

#18楼 @huobazi CSDN 曾经用 UUID 的?好,我去查查他们为什么后来不用了。

15

#19楼 @kgen 应该是 @robbin 重构的时候,换成 int 了

21楼 已删除
594

@kgen 你的问题,让我想起了我们曾经的一个问题。 我们采用UUID作为mysql数据库的辅助键,而不是主键,主键依然是Int ID 我们的情况可能不一样,为了说明我们的情况我写了这个帖子, 为支持移动端离线模式-数据库采用 UUID 字段

370

#23楼 @ery 看完了你那篇遗留系统转向支持 UUID 的实战经历,感谢分享。 另外,文采很好,幽默

10677

最近遇到一个场景跟楼主的问题有点参考性。我们有很大量的数据要处理,此时如果用数字就可以很方便分区,新数据是大ID,使用新机器处理,也方便扩容。但是我们现在的数据identity是md5,这样容易分区(比如按照md5的第一个字符)但是不好扩容了,因为新数据仍然落在MD5这个大的key空间中

96

主键肯定应该是int型的,uuid不符合要求 楼主可以搜索下flickr的分布式ticket server,就是一句mysql语句,充当类似oracle的sequence功能,专门用来生成全局唯一的数字

96

从我的使用经验上面来说,mysql 的主键还是保持默认 int 比较好,对数据迁移什么的比较友好,如果真需要 uuid,不妨切换到支持更好的 postgres 或者 mongodb 吧。

8

#28楼 @huobazi 被你的热门标签吓尿了...

15

#29楼 @hooopo O(∩_∩)O哈哈~,我不是故意滴

3001

参考MongoDb的ObjectID挺好的。。。

96

uuid的问题是:

  1. 纯字符串类型,算上连字符'-'的话,36个字符。而整数类型最大bigint也就8个字节。
  2. 对 innodb存储引擎来说,主键作为聚集索引,有序地插入(递增)比无序插入性能要好。而uuid 并不是有序的。

所以解决办法是,自己生成绝对不会冲突的纯数字递增主键。 Instagram 的做法同样适用于 mysql,见 http://instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagram

7853 ibugs Schema 与数据类型优化小技巧 中提及了此贴 08月30日 11:44
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册