经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » 编程经验 » 查看文章
【杂谈】主键ID如何选择——自增数 OR UUID?
来源:cnblogs  作者:猫毛·波拿巴  时间:2025/2/20 10:39:12  对本文有异议

1.生成位置如何影响选择?

数据库往返时间

使用自增数时,ID是由数据库在执行INSERT操作时生成的;而UUID则可以在应用层生成。

考虑这样的场景:

一个方法需要插入A和B两个实体。其中B的数据需要引用A的ID。

如果使用自增ID,则必须与数据库进行两次网络请求:

1.先插入A,获取A的ID;

2.然后使用A的ID构建B,再插入B。

而如果使用UUID,可以在应用层同时生成A和B的ID,之后一次性将两个实体提交给数据库,从而减少网络往返的次数,提高效率。

ID冲突

自增数在一个表内不会冲突,那两个表呢?

当业务发展到需要分库分表的时候,就不能再使用自增数作为ID了,因为两个库/表会生成相同的ID。这种ID冲突且不报错的问题,会导致数据混乱。

UUID虽然具有全球唯一性,极端情况也会有冲突,所以应用层需要想办法处理,确保ID唯一性,例如IID生成结合机器ID。

2.有序与无序如何影响选择?

ID是否有序对数据库性能有重要影响,特别是使用B-Tree索引。

有序的ID:对B-Tree索引来说,键值有序,那么连续插入的数据都会一个或少数几个节点上,这意味着,数据库只需要对少量的物理块进行I/O读写,I/O范围小,性能较好。

eg:连续插入20条数据,都在一个节点上,只要加载一个物理块。

无序的ID:键值无序,那么连续插入的数据可能随机分布在各个节点上,数据库就需要对大量的物理块进行I/O读写,性能较差。

eg:连续插入20条数据,经计算它们分布在20个不同节点上,需要加载20个物理块。

 

显然,自增ID是有序的,所以在大多数情况下,它的性能优于无序的UUID。

值得一提的是,UUID也有多个版本,其中一些是有序的,例如UUIDv7和雪花算法(Snowflake)

而Java JDK默认使用的UUID是v4版本,是无序的。

3.ID大小如何影响选择?

ID大小指占用的存储空间。自增数通常是INT或BIGINT,分别是4字节和8字节。UUID一般由32个字符组成,占16字节。

树的高度

在B-Tree中,对于固定大小的节点,键值大小会影响一个节点能存储的键值数量(这里就是ID数量)。影响了单个节点存储的键值,就会影响节点数量,进而影响树的高度。

而树越高,一次查询需要访问的节点就更多,查询就更慢。

内存开销

相同数量的记录,ID的大小会影响到数据库引擎的缓存(索引和数据行)。同样大小的缓存空间,单个ID越大,能缓存的数据就越少。

例如:InnoDB使用innodb_buffer_pool_size控制缓存池大小

总结

总的来说,有序的UUID(UUIDv7,雪花算法)更适合分布式服务,自增ID更适合单机服务。

但是也要看具体业务,举个例子,如果分表的数据不存在跨表访问的情况,那么ID冲突就冲突了,没有任何影响。

而且,ID策略也能混着用,一个数据库里面不同表可以用不同的ID生成策略。

原文链接:https://www.cnblogs.com/longfurcat/p/18724563

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号