uuid作为主键,还是用自增呢?
回复内容:
我在网上找了好久,有的人说uuid比较好,就是在分库分表,合并数据什么的比较容易,也有的人说自增好,到了表的数据多的时候,性能比uuid好得多,到底那种比较好呢?有没有在真实生产环境的大神,来给出一个完整的解答?
首先UUID
的性能并不比自增ID
差很多,这取决于UUID
的生成算法。举个例子MongoDB
所采用的ObjectId
就是一个比较优秀的UUID
策略,其组成是时间戳+机器码+进程码+自增数
,其中机器码和进程码都可以一次性生成,这样得到一个ObjectId
仅仅之比自增ID
多了一个时间戳的获取。另外考虑到自增ID
都要做主键唯一索引,而UUID
可以只做索引,不做唯一索引(利用其特性,可以不考虑唯一性过滤),其性能可以说并不比自增ID
差。
至于使用UUID
还是自增ID
主要还是看项目是否足够庞大,数据量是否足够多。从使用方便性上来说自增ID
使用简单,不需要额外支持,而UUID
相对麻烦一些,涉及到UUID
算法的选取、程序的嵌入等等。而从应对庞大系统的效果上来说,UUID
就比自增ID
显得优秀得多。怎么选择就是看自己的实际情况,按需选择。
Oracle环境下(其他数据库没有使用经验):
长远来说,自增Number的占用空间比UUID(raw(16)占用32字节)更大,但一般表的数据量在数百亿以内时number占用的空间还是更少;
UUID使用没有number方便,UUID存储为raw(16)时查询条件需要使用HEXTORAW转换;
相同行数情况下,基于UUID的索引占用空间比number更大,数据量上去了读取磁盘次数肯定就更多了;
并发或者rac集群环境下,因为热块现象UUID的性能高于number(建立反向索引可解决这个问题);
UUID使用于前台展示时更安全,Number可以猜测
如果这个 id 会暴露给用户的话(URL的一部分),那么自增ID 更友好。
性能方面 2 个差距不太大
-
开发方便性的话,UUID 比 自增ID 要方便的多
UUID 可以解决分布式ID不冲突,数据库自增ID不支持。
UUID 可以在提交数据库之前就获取,不需要多一个 select 语句
不是所有数据库都支持自增ID
UUID可以不采用标准的36位长度,可以用base64压缩到12-16位长度。
优先采用UUID方案,如果需要更友好的 URL,也应该采用 sequence 代替自增ID
上面大部分答案从开发人员角度比较uuid生成效率,而对数据库的存取效率案例看,用InnoDB或TokuDB的话,答案就是自增主键,看看Oracle ACE的这篇解答:
为什么InnoDB表要建议用自增列做主键
按需所取,具体问题具体分析,简单的说,一般 32字节的UUID 可以通用
自增在索引上有优势(整型的比较比字符串比较要快),但优势有限。两者的区别最主要在于id是在client端/server端生成。 相对于mysql来说,java程序就是一个client端。uuid可以保证client端生成一个唯一且不重复的id,这在分布式系统中非常重要。
如果你摸不准的话,我建议你使用uuid.
这个要看你底层存储的选型,Oracle我不熟,他底层使用rowid来完成,所以不发表评论。其他类似MongoDB等都有自己特殊性,所以用UUID倒反合适。
但如果你的底层存储用MySQL,而且存储引擎又恰好是Innodb,那我是非常推荐你使用唯一自增的数字来作为你的PK;
首先不去探讨UUID和long这两个数据在CPU进行计算时分别对应多少个指令和CPU计算周期,最重要的是Innodb的底层存储是B+Tree,需要按照一个聚集索引,所有的数据查询操作都是基于聚集索引来完成(如果表设计了PK,则聚集索引默认选用就是这个PK)
如果InnoDB表的数据写入顺序能和B+树索引的叶子节点顺序一致的话,这时候存取效率是最高的。
当然了,如果你的系统不追求性能的极限,那随便玩
为什么不定制自己的主键策略呢?
mysql的使用自增的,不然innodb也要自己维护主键索引的。
如果是单机, 推荐使用mysql的自增id.
如果是分布式环境, 想要保持全局的唯一id, 自增和uuid都不行。
这个时候就需要自已定制一套id生成机机制了
【注意】
我遇到过GUID重复,所以,直接用GUID做唯一主键是有潜在问题的!
(GUID是UUID标准的一种实现)
这个感觉还是要看具体的场景吧,如果只是一台数据库服务器的话,并且业务逻辑并不复杂,完全可以使用自增ID的方式,简单开发;如果是仅有少量的几台主数据库服务器也可以使用自增ID,但需要做一些处理。
对于分布式的,也就是有多台主数据库服务器的情况再使用自增ID就会使开发变得复杂,自增ID会变得越来越难控制,这时候何不用UUID呢,毕竟两者的性能也没差多少