博客完整译文: 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 性能,但是不管怎么样这都会提高查询的延迟。
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.