【杂谈】主键ID如何选择——自增数 OR UUID?
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生成策略。
【杂谈】主键ID如何选择——自增数 OR UUID?的更多相关文章
- Mysql对自增主键ID进行重新排序
Mysql数据库表的自增主键ID号经过一段时间的添加与删除之后乱了,需要重新排列. 原理:删除原有的自增ID,重新建立新的自增ID. 1,删除原有主键: ALTER TABLE `table_name ...
- Mysql自增主键ID重新排序方法详解
Mysql数据库表的自增主键ID号乱了,需要重新排列. 原理:删除原有的自增ID,重新建立新的自增ID. 1,删除原有主键: ALTER TABLE `table_name` DROP `id`; 2 ...
- 使用mybatis插入自增主键ID的数据后返回自增的ID
在开发中碰到用户注册的功能需要用到用户ID,但是用户ID是数据库自增生成的,这种情况上网查询后使用下面的方式配置mybatis的insert语句可以解决: <insert id="in ...
- Mybatis+Mysql插入数据库返回自增主键id值的三种方法
一.场景: 插入数据库的值需要立即得到返回的主键id进行下一步程序操作 二.解决方法: 第一种:使用通用mapper的插入方法 Mapper.insertSelective(record): 此方法: ...
- mybaits返回自增主键ID
mybaits两种获取自增主键ID的方法:一种是使用useGeneratedKeys,第二种是selectKey方法获取. useGeneratedKeys <insert id="i ...
- Mybatis 中获取添加的自增主键ID(针对mysql)
分享一篇博客,主要就是针对在我们使用SSM的时候,在.xml中获取<insert></insert> 时的自增主键Id,由于好久没有,这个时候使用,有点生疏,就在这里写个笔记, ...
- Mybatis 在 insert 之后想获取自增的主键 id
记录一次傻逼的问题, 自己把自己蠢哭:Mybatis 在 insert 之后想获取自增的主键 id,但却总是返回1 错误说明: 返回的1是影响的行数,并不是自增的主键id: 想要获取自增主键id,需要 ...
- 将一张表的主键(ID)重置为从1开始自增排列
如果你有一张表,你的主键是ID,然后由于测来测去的原因,你的ID不是从1开始连续的自增了. 终于有一天,使用这张表的某个系统要导入正式数据了,强迫症这时候就表现的明显了,浑身不自在, 这时候你就需要将 ...
- Java中实现MongoDB自增主键ID
1.了解MongoDB的ObjectId MongoDB的文档固定是使用“_id”作为主键的,它可以是任何类型的,默认是个ObjectId对象(在Java中则表现为字符串),那么为什么M ...
- Mybatis 在 insert 之后想获取自增的主键 id,但却总是返回1
记录一次傻逼的问题, 自己把自己蠢哭:Mybatis 在 insert 之后想获取自增的主键 id,但却总是返回1 错误说明: 返回的1是影响的行数,并不是自增的主键id: 想要获取自增主键id,需要 ...
随机推荐
- 一款基于 .NET + Blazor 开发的智能访客管理系统
前言 在小区.企业.学校等场所,访客管理作为日常运营中不可或缺的一环,其重要性日益凸显.传统的访客管理方式往往依赖于人工登记.纸质记录,不仅效率低下,还存在信息易丢失.难以追溯等问题.今天大姚给大家分 ...
- C#生成Guid的几种方式-迷恋自留地
var uuid = Guid.NewGuid().ToString(); // 9af7f46a-ea52-4aa3-b8c3-9fd484c2af12 var uuidN = Guid.NewGu ...
- C#向JAVA发送form-data文件问题处理方案
前言 和上一篇文章一样,.NET 和 JAVA之间的接口请求又遇到了新问题 我们有一个用来接收文件的接口,外部把文件流.文件名.目录,传进来,我们系统把生成的附件ID反回去,接口为POST-form- ...
- C/C++源码扫描系列- codeql 篇
首发于 https://xz.aliyun.com/t/9275 概述 codeql 是一个静态源码扫描工具,支持 c, python, java 等语言,用户可以使用 ql 语言编写自定义规则识别软 ...
- 【Android】谷歌应用关机闹钟 PowerOffAlarm 源码分析,并实现定时开、关机
前言 RTC RTC 即实时时钟(Real-Time Clock),主要是功能有: 时间保持:RTC可以在断电的时候,仍然保持计时功能,保证时间的连续性 时间显示与设置:RTC可以向系统提供年.月.日 ...
- ORM框架与数据库交互
title: ORM框架与数据库交互 date: 2024/12/22 updated: 2024/12/22 author: cmdragon excerpt: 对象关系映射(Object-Rela ...
- adduser和addgroup命令讲解
https://wiki.alpinelinux.org/wiki/Setting_up_a_new_user 在Alpine Linux下创建用户和组命令分别是adduser和addgroup,本文 ...
- IDEA批量实现CRLF转换成LF问题
需要注意idea项目中右下角:选择LF,否则到时候部署到生产环境上会报错'\r\n'问题,之前的解决方案是 dos2unix 然后很多文件报这个问题,索性进行批量转换,但是很快拉去的新项目又会出现同样 ...
- Qt/C++音视频开发64-共享解码线程/重复利用解码/极低CPU占用/画面同步/进度同步
一.前言 共享解码线程主要是为了降低CPU占用,重复利用解码,毕竟在一个监控系统中,很可能打开了同一个地址,需要在多个不同的窗口中播放,形成多屏渲染的效果,做到真正的完全的画面同步,在主解码线程中切换 ...
- Qt开源作品24-遮罩层窗体
一.前言 在有些项目中,需要在弹框的窗体背后遮罩原有主窗体,使得突出显示弹窗窗体,突然想到之前写过一个全局截屏的东东,原理一致,拿来改改.只需要引入一个头文件和实现文件,然后在主窗体中设置下需要遮罩的 ...