UUID 做主键有什么优势和劣势?

2019-09-06 15:01:06 +08:00
 aaronysj

之前做过的项目,基本都是用自增 id 做主键或者没有主键。这次领导突然说用 UUID varchar(36)位做主键,让小弟有点迷惑,望大家指点迷津。

18131 次点击
所在节点    程序员
77 条回复
wlw0327
2019-09-06 15:43:12 +08:00
优势就是全局唯一了,但是劣势嘛,性能会差
Valid
2019-09-06 15:43:31 +08:00
主键还是自增,给每条数据分配 uuid 不是更好?有问题?
tanszhe
2019-09-06 15:43:50 +08:00
优势是可分布式唯一

劣势性能差,浪费空间 和 自增比
jzmws
2019-09-06 15:46:24 +08:00
雪花了解一下 .
jzmws
2019-09-06 15:47:06 +08:00
@chendy 雪花超级好用 ,数字主键对新能提升也超级棒
lbp0200
2019-09-06 15:51:16 +08:00
UUID 性能差?少写点 bug,什么都有了
Aresxue
2019-09-06 15:51:40 +08:00
优点:
1.可以用来做分布式 id 更方便;
2. 具有唯一性, 可以让数据分布的更均匀;
3.字符串可以屏蔽掉 java 和 js 的一些数据类型差异,比如使用 Long 时如果数字过大会产生问题;
缺点:
1.太长了,主键会被用作聚簇索引,每次插入都要损耗不少性能,bigint 也才 8 个字节;
2.临近的数据没有相关性,不能有效利用局部性原理节省性能;
3.进行范围查询时会扫描过多的页,性能不好,这点和 2 类似。
优先推荐 Twitter 的 snowflake,但需要记得在最外层和前端交互时使用 String
passerbytiny
2019-09-06 16:19:17 +08:00
优势:完全业务无关,完全与数据库无关,意味着生成迅速、生成简单、全局统一、不依赖底层基础设施。
劣势:完全业务无关,完全与数据库无关,意味着不是自然主键(你需要另加唯一索引字段才能有自然主键)、不直观、底层基础设施的性能优化措施用不上。

至于前面那些人所说的“太长”的劣势,这纯粹是人云亦云,早期存储值钱的时候还可以这么说,现在都大数据了,还这么说就是扯淡。另外,UUID 本质上是 16 字节 128 位二进制数据,如果没有特殊需要(懒得加额外的自然主键,直接拿 UUID 做不那么高效的自然主键),那么 UUID 就没必要再 dump 成 32/36 字节的字符串,直接用十六字节长度二进制类型进行存储。
lihongjie0209
2019-09-06 16:27:30 +08:00
数据库无关, 你的几百行业务代码中, 各种数据库插入就是为了获取自增 ID, 然后给后面业务逻辑用。

如果我们使用 UUID, 那么你的业务代码中数据库操作出现的概率会小很多, 方便测试, 也是一种解耦
ryd994
2019-09-06 16:35:09 +08:00
UUID 用什么 varchar ?
首先 UUID 是定长的,不需要变长类型。定长类型在储存和索引时有优势
其次 UUID 是 hex,一共才 36 种字母数字,为什么作为 text 存?任何 UUID 完全可以导出为二进制
数据库提供 UUID 数据类型时存 UUID 类型。原因是比较顺序。UUID1 前几位是机器代号,最后才是随机数。所以最好从后往前建立索引,这样可以帮助索引自然平衡。

UUID 最适合分库的情况,UUID 的随机性保证了分库的平均。同时结合机器代号可以保证不同机器无需单点也能保证不碰撞。
ryd994
2019-09-06 16:44:37 +08:00
最后,主键只是数据库内在的储存结构的一部分。如果你用的是单机或者客户端了解的分表分库,那自增主键的性能反而更好
楼上说什么方便给用户的,你自己想想看,数据库主键直接暴露给用户,这是求人碰撞攻击你吗?给用户看到的 token 为什么不和内部 ID 解耦? token 和 id 解耦之后还能 revoke
就算用自增主键,也可以另外生成一个带索引的 token 字段,隐藏用户 ID 和主键用什么,没有半毛钱关系

再吐槽一下 varchar 做主键,存的是 UUID。真的不知道在想什么。任何读过数据库的用户手册的人都想不出这样的主意。你就没有想过为什么某些数据库要专门做个 UUID 类么?
ryd994
2019-09-06 16:48:45 +08:00
@passerbytiny 和储存无关,主键要进索引的。硬盘是不值钱,但是 1.内存值钱 2.CPU cache 值钱 3.硬盘 IO 操作数量 /延迟值钱
能不能用?能
但是数据量上来以后性能会很差
ryd994
2019-09-06 16:55:23 +08:00
@wysnylc 正确使用 UUID1 是不会有碰撞的。要碰撞需要你在 100 纳秒内反复生成还刚好遇上随机数碰撞
UUID4 是纯随机,鉴于值域有 128bit,你可以算算 10 年内碰撞到一次需要多高的频率。实际上也基本可以忽略,当然,比不上 UUID1 的绝对保证。优点是不依赖,不暴露机器信息
其他 UUID 各有生成逻辑,使用之前彻底搞懂生成逻辑,然后论证为什么可以避免碰撞即可。
zjiecode
2019-09-06 16:58:49 +08:00
最直接的好处是,避免被穷举
Raymon111111
2019-09-06 17:04:15 +08:00
劣势
1. 不自增, 插入性能会有点问题. 这个和索引的结构有关系, 往中间插一个数据如果遇上当页数据满了后面都得重做

2. 数据量大一点碰撞是很常见的, 或者可以说是必现的, 按天维度 (这个可以搜一下别人的使用经验)
wanguorui123
2019-09-06 17:18:26 +08:00
UUID 优势:
1、避免 API 接口传入恶意 ID,试图绕过验证
2、分库不用担心 ID 冲突
3、web 端不用考虑 ID 精度丢失,因为是字符串
3、UUID 理论上无限大,可以认为插入无限量的 ID,而序列是有限的

UUID 劣势:
1、相对序列耗费资源
2、文本的索引效率相对低了一点
yalin
2019-09-06 17:21:23 +08:00
减少对具体数据库的主键依赖
dk7952638
2019-09-06 17:21:42 +08:00
雪花也不是没有缺点,对系统时钟有严格要求
wanguorui123
2019-09-06 17:22:43 +08:00
UUID 优势:
1、避免 API 接口传入恶意 ID,试图绕过验证
2、分库不用担心 ID 冲突
3、web 端不用考虑 ID 精度丢失,因为是字符串
4、UUID 理论上无限大,可以认为插入无限量的 ID,而序列是有限的
5、不需要维护 ID 的顺序

UUID 劣势:
1、相对序列耗费资源
2、文本的索引效率相对低了一点
sujin190
2019-09-06 17:23:25 +08:00
其实为啥要把表主键和数据主键弄成一个,是不是表自身还是有个自增的 int 主键 ID 更好一些?数据再有个非线性可分布式的数据主键

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/598593

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX