首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >主键的选择:自增id?UUID?雪花算法?

主键的选择:自增id?UUID?雪花算法?

作者头像
用户11288958
发布2025-08-17 08:25:15
发布2025-08-17 08:25:15
28500
代码可运行
举报
文章被收录于专栏:学习学习
运行总次数:0
代码可运行

一、主键为什么不使用自增id

  • 数据迁移和备份:如果你需要将数据从一个数据库迁移到另一个数据库,或者备份和恢复数据,自增主键可能会导致问题。例如,如果你在新数据库中已经存在与旧数据库相同的自增 ID,那么插入操作可能会失败。
  • 删除和插入操作:如果表中存在大量删除和插入操作,自增主键可能会导致 ID 值的不连续。这可能会浪费存储空间,并可能导致某些应用程序或系统逻辑出现问题。
  • 性能问题:在高并发的写入操作中,自增主键可能会导致性能瓶颈。因为每次插入新记录时,数据库都需要找到下一个可用的自增 ID。这可能会增加写操作的延迟。
  • 可预测性:自增主键的值是可预测的,因为它们总是按照递增的顺序生成。这可能会带来安全风险,例如,攻击者可能会尝试预测未来的 ID 值来插入恶意数据。
  • 分布式环境问题:在分布式数据库系统中,自增主键可能会带来挑战。如何保证各个节点生成的自增 ID 是唯一的,这将需要额外的机制来协调各个节点。

二、UUID生成主键(32位16进制)

uuid:UUID(Universally Unique Identifier,通用唯一识别码)是一种软件建构的标准,用于在分布式计算环境中为元素提供唯一的标识信息。UUID共占128位,分为五段,它具有唯一性、全局性、不变性等特点。

uuid生成主键,需要将testId改成String类型  而在数据库建表的时候testId 不能用bigint了 而是用char(32)就可以了 生成的uuid是这样的 c37da8074d52022661db24bf931990af 32个字符,这个16进制写法,展开就是128比特位了

三、雪花算法生成主键(整数0 到 2^64 - 1

雪花算法(Snowflake):是一种分布式唯一ID生成算法,用于生成全局唯一的ID。它的设计目标是在分布式系统中生成ID,保证ID的唯一性、有序性和趋势递增。雪花算法的核心思想是将一个64位的ID分成多个部分,分别表示不同的信息。

1bit:代表是正数,永远为零 41bit:时间戳

  • 时间戳部分占41位,用于记录当前时间,通常以毫秒为单位。
  • 由于41位可以表示的范围非常大,因此可以记录的时间跨度也很长。
  • 起始时间(epoch)通常是某个固定的时间点(例如2022年1月1日),之后的所有时间戳都是相对于这个起始时间的偏移量。
  • 计算公式:当前时间戳 = 当前时间 - 起始时间

10bit:机器标识:

  • 机器标识部分占10位,用于区分不同的机器或节点。
  • 在分布式系统中,可能会有多个节点同时生成ID,这10位可以用来唯一标识每个节点。
  • 10位最多可以表示 2的10次方 = 1024 个不同的机器标识。

12bit:序列号

  • 序列号部分占12位,用于在同一毫秒内生成多个ID时进行区分。
  • 如果同一台机器在同一个毫秒内需要生成多个ID,那么序列号会递增。
  • 12位最多可以表示 2的12次方 = 4096 个不同的序列号,也就是说每毫秒最多可以生成4096个ID。

用雪花算法生成的主键。 java中可以用long型表示 数据库建表用bigint 就像下面这样 1908852570512781314 这是一个用十进制表示的数字

四、为什么不使用UUID作为主键:

  • 存储空间:UUID存储会占用更大的空间,这会增加数据库的存储需求,尤其是在大型数据库或高并发的系统中,这可能会成为性能瓶颈。
  • 索引性能:由于UUID相对较大,使用UUID作为主键会导致索引变得更大,从而影响查询性能。特别是在执行范围查询或JOIN操作时,性能下降可能会更加明显。
  • 可读性:UUID由一串字符组成,不易于人类阅读或记忆。这可能会影响到开发、运维和调试的便利性。

五、使用Mybatis-plus支持雪花算法 

1.引入依赖

代码语言:javascript
代码运行次数:0
运行
复制
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>

2. @TableId(type = IdType.ASSIGN_ID)

//用来指定主键生成策略,使用雪花算法private Long userId;  

//主键  不再使用auto_increment

代码语言:javascript
代码运行次数:0
运行
复制
package com.qyy.system.domain.sysuser;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.qyy.common.core.domain.BaseEntity;
import lombok.*;

import static com.baomidou.mybatisplus.extension.toolkit.Db.save;

@TableName("tb_sys_user")//用来指定表名
@Data // 包含@Getter、@Setter、@ToString、@EqualsAndHashCode、@RequiredArgsConstructor
@NoArgsConstructor // 生成无参构造方法
//用来自动生成getter/setter/toString/equals/hashCode等方法
public class SysUser extends BaseEntity {
    @TableId(type = IdType.ASSIGN_ID)//用来指定主键生成策略,使用雪花算法
    private Long userId;  //主键  不再使用auto_increment

    private String userAccount;//账号

    private String password;//密码

    private String nickName;//昵称

    public static void main(String[] args) {
        SysUser sysUser = new SysUser();
        sysUser.setUserAccount("123");
        System.out.println(sysUser.getUserAccount());
        System.out.println(sysUser);
        save(sysUser);
        System.out.println(sysUser);

    }
}

具体输出内容:

第一行输出:

123

(因为通过 setUserAccount("123") 给 userAccount 赋值后,getUserAccount() 直接返回该值) 第二行输出(示例):

SysUser(userId=null, userAccount=123, password=null, nickName=null, ...)

(由 @ToString 注解自动生成,包含所有字段的当前值。未赋值的字段(如 userId、password 等)会显示为 null,继承自 BaseEntity 的字段(如创建时间、更新时间等)也会显示默认值) 说明:

userId 为 null 是因为此时仅创建了对象,未通过 MyBatis-Plus 的 save 方法保存到数据库,雪花算法的 ID 生成逻辑在保存时才会触发。

其他未赋值的字段(password、nickName 等)也会显示为 null,除非在 BaseEntity 中定义了默认值。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-07-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、主键为什么不使用自增id
  • 二、UUID生成主键(32位16进制)
  • 三、雪花算法生成主键(整数0 到 2^64 - 1)
  • 四、为什么不使用UUID作为主键:
  • 五、使用Mybatis-plus支持雪花算法 
    • 1.引入依赖
    • 2. @TableId(type = IdType.ASSIGN_ID)
    • 具体输出内容:
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档