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

kgen · March 06, 2015 · Last by oxffff replied at April 02, 2015 · 33608 hits
Topic has been selected as the excellent topic by the admin.

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

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

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

还没在生产环境试过。不过看网上资料,主键的字段类型设置引起不同的性能变化 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

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

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

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

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

感觉应该没什么问题吧

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

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

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

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

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

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

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

像 twitter 那样搞就可以了

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

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

看看 csdn 论坛 又换回来了

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

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

21 Floor has deleted

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

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

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

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

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

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

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

参考 MongoDb 的 ObjectID 挺好的。。。

uuid 的问题是:

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

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

ibugs in Schema 与数据类型优化小技巧 mention this topic. 30 Aug 11:44
You need to Sign in before reply, if you don't have an account, please Sign up first.