# MyBatis-Plus教程 - 4 主键生成策略
什么是主键生成策略?
主键生成策略就是如何为数据库表中的新记录生成唯一的主键 ID 值。
常用的策略有:
- 数据库ID自增 :使用数据库自带的自增策略,ID是整形,随着插入的数据增加;
- 手动输入:在插入的时候,自己设置ID,想要什么ID自己随意指定;
- UUID:一般是32个十六进制数字组成的随机字符串,理论上能够保证全局唯一,但是是没有顺序可言的。
- 雪花算法:雪花算法是Twitter开源的分布式ID生成算法,能够生成一个64位的唯一ID。
通过设置主键生成策略,可以在插入数据的时候,指定主键ID生成的规则。
# 4.1 雪花算法
简单介绍一下雪花算法。
雪花算法(Snowflake)是Twitter开源的分布式ID生成算法,能够生成一个64位的唯一ID。该算法在分布式系统中应用广泛,因为它能够在不依赖数据库的情况下生成全局唯一的ID,并且ID呈递增趋势。
雪花算法生成的ID是64位long型,被分割成四个部分:符号位、时间戳、工作机器ID、序列号。
- 符号位(1位):始终为0,用于标识ID是正数。
- 时间戳(41位):时间戳为41位,精确到毫秒级,时间戳保证了ID的唯一性和时间有序性。但是同一个时间可能生成多个ID,所以需要使用了后面的机器ID。
- 机器ID(10位):用于标识生成ID的机器,每台机器都有一个唯一的ID,以确保在同一系统内不同机器生成的ID互不冲突。但是同一台机器同一个时间戳内可能生成多个ID,所以还需要使用序列号。
- 序列号(12位):用于在同一毫秒内生成多个ID。序列号在同一毫秒内从0开始递增,当达到最大值(如4095)后会回绕到0。也就是支持1台机器1毫秒生成4096个ID,超过了,得等下一毫秒。
# 4.2 主键生成策略对比
为什么在实际开发中,不建议使用自增 ID 或 UUID 作为主键,而推荐使用雪花算法呢?
# 1 自增ID
自增ID在单节点系统中没有问题。但在分布式系统中,各节点可能使用不同的数据库实例,导致不同节点生成的 ID 出现重复,难以保证全局唯一性。
# 2 UUID
UUID 可以保证全局唯一性,但其生成的字符串长度较长,通常需要32个字节,虽然 UUID 是随机生成的,可以保证分布式系统中全局唯一性,没有任何顺序性,导致在数据库中插入数据时,可能会触发频繁的索引页分裂,影响性能。
UUID 的生成也是遵循一些规则,例如时间、IP等信息,这里就不过多介绍了。
# 3 雪花算法
雪花算法生成的 ID 是 64 位长的整数,占用 8 字节的空间,能够在分布式环境下保证唯一性,同时长度适中。因为 ID 包含时间戳,因此大部分情况下是有序的,能够提高数据库索引的插入效率,减少索引页分裂的可能性。另外雪花算法无需依赖数据库或外部服务,生成速度非常快。
所以,雪花算法在分布式系统中具有全局唯一性、有序性、节省存储空间和高性能等优点,因此在实际开发中,特别是在需要高并发和分布式场景中,推荐使用雪花算法生成 ID,而不建议使用自增 ID 或 UUID。
# 4.3 修改主键生成策略
设置或修改 MyBatis-Plus 中的主键生成策略有两种方式:全局设置 和 针对某个表设置。
# 1 全局设置
MyBatis-Plus 默认使用的是雪花算法的生成策略,如果要修改主键的生成策略,可以在 application.yaml
配置文件中修改:
# mybaits-plus配置
mybatis-plus:
global-config:
db-config:
# 主键生成策略
id-type: AUTO
2
3
4
5
6
id-type
可以设置为如下的值:
- AUTO:主键自增,需要在数据库中设置字段为主键自增,类型可以是
INT
或BIGINT
,根据自己的业务量。 - INPUT:自己指定数据的ID,自己设置。
- ASSIGN_ID:雪花算法,雪花算法的长度是64位,最大值转换为10进制长度是19,所以在创建数据库表字段的时候,使用
BIGINT
来保存即可。 - ASSIGN_UUID:UUID,设置为UUID,需要将数据库中的字段设置为字符串,长度最少设置为
32
。
上面设置的是全局的主键生成策略,还可以针对不同的表去设置。
# 2 单个表设置
针对单个表来设置主键生成策略,需要在数据库表对应的 Java 实体类中使用 @TableId
注解来设置。
@Data
@TableName("tb_user")
public class User {
@TableId(type = IdType.ASSIGN_ID)
private String id;
// ...略
}
2
3
4
5
6
7
8
9
除了可以指定为 AUTO
、INPUT
、ASSIGN_ID
、ASSIGN_UUID
之外,还可以指定为 NONE
,指定为 NONE
或不指定,都表示使用全局的主键生成策略。