ID 是系统开发中最基本的一个字段,针对 ID 目前多种方案:自增、UUID、雪花算法等,下面针对这些方案做一个对比(基于 mysql 数据库):
自增 ID
自增 ID:有序 ID
优势:性能好、存储内容少、不会有页裂变问题、易读
劣势:分布式存储比较麻烦、mysql 有自增的 id 锁会有一定性能损耗(相对的)、容易被猜测数据被爬虫爬取
要支持分布式也可以,就是分表分库的时候设置不同的起始递增的位置
比如:表 A1 起始 101000000000,表 A2 起始 102000000000,这样 ID 就不会相同,预留 10 亿的数据,前面三位作为区分不通表或者机器
UUID
UUID:无序随机 ID,时间戳 + 随机数 + 机器 MAC 等信息
优势:全网唯一、适合分布式分库分表存储、ID 没有规律不会被恶意猜测
劣势:性能 / 性能 / 性能、随机导致数据库存储大量的页 (插入性能会有比较大的影响,数据量非常大的时候查询也会有影响)、存储内容也较大(多了一倍多的存储空间)
关于 UUID 还有一种有序 UUID,有序 UUID 会有更好的性能,Hibernate 依赖包中有关于有序 UUID 的实现类:org.hibernate.id.UUIDHexGenerator。
如果项目中一定要使用 UUID 的话建议使用有序 UUID。
雪花算法
雪花算法:Snowflake,时间戳 + 随机数 + 服务器标记
优势:性能较好、有序、全局唯一适合分布式场景
劣势:存储内容较长、前端 Long 转换有精度丢失问题(需要实现 Json 转换解决精度问题)、服务器时钟回拨问题导致重复 ID (概率较低)、插入性能没有自增 ID 好
精度问题处理:https://www.jianshu.com/p/190a18b3d56c
几种 ID 生成方式的压力测试对比:
创建 4 种 ID 类型的表:
自增
CREATE TABLE `test_id` (
`id` bigint (20) NOT NULL AUTO_INCREMENT COMMENT ' 主键 ',
`name` varchar (200) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT ' 名称 ',
`remark` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_CREATETIME0` (`create_time`)
) ENGINE=InnoDB AUTO_INCREMENT=1324008 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
雪花
CREATE TABLE `test_snowflakeid` (
`id` bigint (20) NOT NULL COMMENT ' 主键 ',
`name` varchar (200) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT ' 名称 ',
`remark` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_CREATETIME1` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
随机 UUID
CREATE TABLE `test_uuid` (
`id` varchar (100) COLLATE utf8_unicode_ci NOT NULL COMMENT ' 主键 ',
`name` varchar (200) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT ' 名称 ',
`remark` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_CREATETIME2` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
有序 UUID
CREATE TABLE `test_uuid2` (
`id` varchar (100) COLLATE utf8_unicode_ci NOT NULL COMMENT ' 主键 ',
`name` varchar (200) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT ' 名称 ',
`remark` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`create_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `IDX_CREATETIME3` (`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
100W 数据
插入对比:
自增: 耗时:180400ms
雪花算法: 耗时:215766ms
随机 UUID: 耗时:719659ms
有序 UUID: 耗时:224371ms
查询 count 对比:
自增:0.5S
雪花算法:0.6S
随机 UUID:2.6S
有序 UUID:0.6S
查询单一记录查询对比:
自增:0.035S
雪花算法:0.032S
随机 UUID:0.040S
有序 UUID:0.035S
时间索引范围查询:
自增:select * from test_snowflakeid where create_time = '2022-02-15 14:01:13'; 0.031S
雪花算法:select * from test_snowflakeid where create_time = '2022-02-15 14:08:18'; 0.04S
随机 UUID:select * from test_uuid where create_time = '2022-02-15 14:16:39'; 0.38S
有序 UUID:select * from test_uuid2 where create_time = '2022-02-15 14:30:28'; 0.038S
结论:
插入性能:自增 > 雪花 = 有序 UUID >(3-4 倍) 无序 UUID
查询 Count 性能:自增 > 雪花 = 有序 UUID >(3-4 倍) 无序 UUID
查询单条记录:自增 = 雪花 = 有序 UUID = 无序 UUID 差别不大
查询时间范围索引:自增 > 雪花 = 有序 UUID >(5-10 倍) 无序 UUID
建议开发的时候使用雪花算法或者有序 UUID。