博客完整译文: https://blog.2014bduck.com/archives/287
原文标题:UUIDs are Popular, but Bad for Performance — Let’s Discuss
原文链接: https://www.percona.com/blog/2019/11/22/uuids-are-popular-but-bad-for-performance-lets-discuss/
作者:Yves Trudeau
翻译时间:2019-12-28
InnoDB 将表中的行存储在主键的 B 树中,在数据库中我们称之为聚簇索引。聚簇索引自动将数据行按主键顺序排列。
当你插入一行随机主键值的数据,InnoDB 需要找到这行应该属于哪一页,如果页没在缓冲池中则将其加载进缓冲池,插入数据行,最后将脏页刷回磁盘。纯随机值加上大表使得 B 树上的每个叶子节点都有机会插入行,而没有热点数据页。数据行不按照主键顺序(译注:主键顺序指主键顺序的末端)插入会导致页的分裂,进一步导致页的填充因子降低。在缓冲池中,有新数据插入的页称为脏页。而缓冲池中的页在被刷回磁盘前再次有新数据需要写入的概率很低。所以大部分时间中,每次插入操作会导致两次 IO 过程——一次读取和一次写入。所以首先 UUID 会对 IO 操作的比例造成影响,而这个又是伸缩性的主要限制因素。
硬件上来讲,获得高性能的唯一方法就是使用低延迟和高耐久的存储介质。然而这又是一个对性能造成影响的因素。因为聚簇索引的存在,辅助索引需要使用主键值作为指针。主键 B 树的叶子节点存储数据行,而辅助索引的叶子节点存储主键值。
我们假定有一个 UUID 作主键的表,并且有 5 个辅助索引,一共 10 亿行数据。如果你读了前面的段落,你会知道每行主键值被存了 6 次。也就是说一共 6 亿的 36 字节字符串值,216GB。这只是冰山一角而已,因为表通常还会有外键,显式或者隐式地指向其他表。当表是基于 UUID 设计的时候,列或者索引需要以char(36)
来容纳数据。最近我分析了一个基于 UUID 的表,发现 70%的存储空间都用来存放 UUID 值。
不止这些,UUID 还有第三点影响。整型在 CPU 中一次性可以比较 8 字节,而 UUID 是逐字节比较的。数据库很少会受限于 CPU 性能,但是不管怎么样这都会提高查询的延迟。
原文很长很长很长,希望大家不要只看了标题就说UUID如何如何,不仅仅是UUID,还有很多hash类型的也是类似,主要讨论的是导致页分裂->每个页填充因子低 & 字段长->多个索引保存主键作为书签导致体积大的坑,然后作者给了几种Option并且给出了测试结果
1
wysnylc 2019-12-28 19:45:45 +08:00 via Android
分布式没法自增主键,就这么简单
|
2
xupefei 2019-12-28 20:01:09 +08:00 via iPhone
研究了这么多年数据库,我现在才知道还有用 uuid 做主键这种玩法😂
|
3
RedisMasterNode OP @wysnylc 其实这个 topic 的重要问题是在于 UUID 如何影响的,分布式也好,单点也好,都没有关系,需要找到一种方案减少数据页分裂后导致的碎片和散列数据对 Buffer Pool 的影响。。。其实应该关注文章内容,而不是标题。。。
|
4
encro 2019-12-28 20:06:39 +08:00
InnoDB 本省主键采用 B+,是有序存储的,用 uuid 存储大量数据得不偿失。
|
5
RedisMasterNode OP @encro 但是要考虑到就算是 UUID 也可以做成区间有序的,这样同样可以减少页的分裂
|
6
qsnow6 2019-12-28 21:44:16 +08:00
分布式用 UUID 没毛病
|
7
sagaxu 2019-12-28 21:51:25 +08:00 via Android
@wysnylc 分布式可以按区自增,比如前 16bit 表示 node,每个 node 有 48bit 的自增区间
|
8
love 2019-12-28 21:58:05 +08:00
印象中我记得 UUID 不是 char(36)啊,而是 binary(16),节省一倍呢
|
9
xuanbg 2019-12-28 22:37:32 +08:00
我们一直用 uuid 作为主键,综合下来好处比坏处多。如果你们都是单表几千万上亿的,能够挽救你的也不可能是自增 ID,而是类似雪花算法的分布式唯一 id。
|
11
laminux29 2019-12-28 22:43:21 +08:00
1.任何方案都有其优缺点。
2.如果因业务限制,只能采用某方案,那就应该先解决业务,再来想办法优化。 |
12
23571113 2019-12-29 04:21:01 +08:00
吓得我又去看了遍教材
|
13
whalegao 2019-12-29 08:37:50 +08:00 via iPhone
用近似自增主键就好了
|
14
br00k 2019-12-29 09:11:03 +08:00 via iPhone
我挺喜欢 mongodb 的 ObjectId 的生成规则。
|
16
binux 2019-12-29 09:53:09 +08:00 via Android
Postgres yes!
|
17
RedisMasterNode OP @levelworm 这东西怎么会有啥教材,有教材无非也就是抄手册上的内容再复述一遍
https://dev.mysql.com/doc/refman/8.0/en/innodb-storage-engine.html 当然偶尔也会有像姜承尧这种大牛出来写书,不过极少极少,至少到目前为止就 1 本 |
18
zhxjdwh 2019-12-29 10:32:43 +08:00 via Android
有序的 uuid 会好点吗
|
19
tairan2006 2019-12-29 12:09:18 +08:00
@wysnylc 阿里云 RDS 直接兼容 mysql 的 Auto Increment 啊…无缝升级
|
20
MoccaCafe 2019-12-29 13:45:13 +08:00
一般数据库有 uuid 类型的,实际上是类似于 int 有序的形式,性能也不会特别差
|
21
optional 2019-12-29 13:51:31 +08:00 via iPhone
uuid 用 36 字节? 16 字节就够了啊
|
22
RedisMasterNode OP 做了个简单的小测试,乱序 32 位 MD5 ID vs 顺序 32 位字符串整数 ID vs 子增 ID 导致的页分裂次数,50000 条数据 INSERT:
```SQL mysql> SELECT NAME, COUNT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE '%split%'; +---------------------------------+-------+ | NAME | COUNT | +---------------------------------+-------+ | index_page_splits | 406 | +---------------------------------+-------+ 1 rows in set (0.00 sec) mysql> SELECT NAME, COUNT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE '%split%'; +---------------------------------+-------+ | NAME | COUNT | +---------------------------------+-------+ | index_page_splits | 288 | +---------------------------------+-------+ 1 rows in set (0.00 sec) mysql> SELECT NAME, COUNT FROM INFORMATION_SCHEMA.INNODB_METRICS WHERE NAME LIKE '%split%'; +---------------------------------+-------+ | NAME | COUNT | +---------------------------------+-------+ | index_page_splits | 193 | +---------------------------------+-------+ 1 rows in set (0.00 sec) ``` |
25
lolizeppelin 2019-12-29 22:59:40 +08:00
要加上定语 MYSQL
其他数据库 uuid 似乎没问题哦 哈哈哈 更别说时间序的 uuid 了 |
26
RedisMasterNode OP @lolizeppelin 为什么,不是特别了解,但是 InnoDB 应该表达得比较明确了个人认为?据我所知 InnoDB 都是 B+树的索引组织表,如果不是的话请举出具体反例
|
27
hooopo 2019-12-30 13:09:17 +08:00
单机搞什么 uuid,分布式 uuid 也没用
|
28
RedisMasterNode OP 早知道就把标题改成散列 ID 的影响了...大家反正都不看内容只看标题..
|