您当前位置:2021欧洲杯买球 > 2021欧洲杯买球手机版 > 正文

使用uuid作为数据库主键,被技术总监怼了一顿!

时间:2021-06-22  来源:未知   作者:admin

本文转载自微信公众号「Java极客技术」,作者鸭血粉丝。转载本文请联系Java极客技术公众号。  

 一、摘要

在日常开发中,数据库中主键id的生成方案,主要有三种

数据库自增ID

采用随机数生成不重复的ID

采用jdk提供的uuid

对于这三种方案,我发现在数据量少的情况下,没有特别的差异,但是当单表的数据量达到百万级以上时候,他们的性能有着显著的区别,光说理论不行,还得看实际程序测试,今天小编就带着大家一探究竟!

二、程序实例

首先,我们在本地数据库中创建三张单表tb_uuid_1、tb_uuid_2、tb_uuid_3,同时设置tb_uuid_1表的主键为自增长模式,脚本如下:

CREATE TABLE `tb_uuid_1` (   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,   `name` varchar(20) DEFAULT NULL,   PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主键ID自增长'; 
CREATE TABLE `tb_uuid_2` (   `id` bigint(20) unsigned NOT NULL,   `name` varchar(20) DEFAULT NULL,   PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主键ID随机数生成'; 
CREATE TABLE `tb_uuid_3` (   `id` varchar(50)  NOT NULL,   `name` varchar(20) DEFAULT NULL,   PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='主键采用uuid生成'; 

下面,我们采用Springboot + mybatis来实现插入测试。

2.1、数据库自增

以数据库自增为例,首先编写好各种实体、数据持久层操作,方便后续进行测试

/**  * 表实体  */ public class UUID1 implements Serializable {      private Long id;      private String name;      //省略set、get } 
/**  * 数据持久层操作  */ public interface UUID1Mapper {      /**      * 自增长插入      * @param uuid1      */     @Insert("INSERT INTO tb_uuid_1(name) VALUES(#{name})")     void insert(UUID1 uuid1); } 
/**  * 自增ID,单元测试  */ @Test public void testInsert1(){     long start = System.currentTimeMillis();     for (int i = 0; i < 1000000; i++) {         uuid1Mapper.insert(new UUID1().setName("张三"));     }     long end = System.currentTimeMillis();     System.out.println("花费时间:" +  (end - start)); } 

2.2、采用随机数生成ID

这里,我们采用twitter的雪花算法来实现随机数ID的生成,工具类如下:

public class SnowflakeIdWorker {      private static SnowflakeIdWorker instance = new SnowflakeIdWorker(0,0);      /**      * 开始时间截 (2015-01-01)      */     private final long twepoch = 1420041600000L;     /**      * 机器id所占的位数      */     private final long workerIdBits = 5L;     /**      * 数据标识id所占的位数      */     private final long datacenterIdBits = 5L;     /**      * 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数)      */     private final long maxWorkerId = -1L ^ (-1L << workerIdBits);     /**      * 支持的最大数据标识id,结果是31      */     private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);     /**      * 序列在id中占的位数      */     private final long sequenceBits = 12L;     /**      * 机器ID向左移12位      */     private final long workerIdShift = sequenceBits;     /**      * 数据标识id向左移17位(12+5)      */     private final long datacenterIdShift = sequenceBits + workerIdBits;     /**      * 时间截向左移22位(5+5+12)      */     private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;     /**      * 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)      */     private final long sequenceMask = -1L ^ (-1L << sequenceBits);     /**      * 工作机器ID(0~31)      */     private long workerId;     /**      * 数据中心ID(0~31)      */     private long datacenterId;     /**      * 毫秒内序列(0~4095)      */     private long sequence = 0L;     /**      * 上次生成ID的时间截      */     private long lastTimestamp = -1L;     /**      * 构造函数      * @param workerId     工作ID (0~31)      * @param datacenterId 数据中心ID (0~31)      */     public SnowflakeIdWorker(long workerId, long datacenterId) {         if (workerId > maxWorkerId 
   

Powered by 2021欧洲杯买球 @2018 RSS地图 HTML地图