作者: kideny 访问次数: 1057 创建时间: 2022-06-08 03:15:29 更新时间: 2024-04-20 14:29:27
2022年5月份,LoserHub网站发生了一起攻击事件。攻击者利用了自己注册的账号,使用模拟浏览器的工具,给LoserHub网站增加了几十万的帖子。由于使用云服务器,数据库每日有备份,所以损失不大。不过,倒是帮我做了一次很好的性能测试,让我发现了使用二进制UUID作为主键的性能问题。
几十万帖子就让MySQL8.0查询异常缓慢
使用二进制UUID作为主键,查询性能差点意思,我是提前知道的。但是,几十万帖子就把MySQL干趴了,我是没想到的。实际上MySQL8.0对于使用二进制UUID作为主键,是有优化的。这也是,当时升级8.0最让我激动的事情之一。有人会说,有现成的雪花算法,为啥一定要用二进制UUID。
说说自己不喜欢雪花算法的一些原因
1,雪花算法只能用69年,虽然可以通过扩充时间戳来扩大这个使用时间,但是我查了一下GitHub现有的库不支持。
2,雪花算法,有一个服务器时间回档可能会产生重复ID的问题。虽然可以通过每次生成ID记住最后一次生成时间的方法来规避,但是麻烦。
3,雪花算法,生成的主键ID太长。19位长整型整数,搞到前端JS的整数只认16位,需要换成字符,又增加麻烦。而且二进制UUID压缩后只有16位,长度比雪花算法短,可以节省数据库的空间,减少索引的大小,降低查询时间。简单说,就是性能更好。
4,实际上,现在已经可以通过生成顺序的二进制UUID,来提高性能了。理论上说,跟雪花算法的数字ID,性能差不了太多。
为什么LoserHub使用二进制UUID作为主键性能那么差?
虽然说,MySQL8.0已经可以通过写入顺序生成的二进制UUID作为主键,来提高索引性能。但是,LoserHub目前的二进制UUID不是通过MySQL8.0数据库生成的。因为当时,开发LoserHub的时候,MySQL8.0还没发布呢。所以,使用的是PHP框架自带的类库生成的UUID。
由于年代久远,我都忘记了这个生成的UUID到底是什么版本的。经过查询,框架自带的类库,生成的是完全无序的符合RF4122规范的V4版本的UUID。即使二进制压缩后,作为主键由于不是循序生成的,性能就很垃圾了。
各位PHP开发人员,如果也想使用二进制UUID作为主键,一定要注意这个问题。
如何生成顺序递增的UUID?
其实根本不需要我们操心这个问题,负责制定UUID规范的国际组织IETF正在制定第6版本的UUID,这个uuid6就是针对性的解决了目前UUID存在的问题。
第一:分散的数据库记录。
第二:无法以有意义的方式按标识符排序(即插入顺序)。
虽然是IETF实验性的草案,但是一些PHP的类库已经支持生成V6版本的UUID了。比如说Ramsey\Uuid了,官方仓库的地址在 ramsey/uuid: A PHP library for generating universally unique identifiers (UUIDs). (github.com).
哇哦,我之前就认为UUID是有前途的主键方案,目前来看是预测准确了。说不定有一天,我们终于可以摆脱雪花算法了,而正大光明的使用UUID作为主键了。
PHP各大框架也有可能跟进
目前PHP的一些关于UUID的类库仅仅作为实验性的功能支持,可以生成V6版本的UUID。随着V6版本的UUID成为正是规范,各大PHP框架也有可能跟进,把生成V6版本的UUID直接集成到框架本身。
作为PHP的开发者,如果不着急,可以像我这样暂时等一等。相信过不了多久,包括PHP在内的各大编程语言,都有可能集成V6版本的UUID功能了。
顺序排列的二进制UUID与BigInt作为主键的性能对比
早在2014年,Pecona官方就发表了一篇文章,《在MySQL中存储UUID值》。就对顺序排列的二进制UUID和雪花算法生成的BigInt作为主键的性能,进行了对比。
大概2500万条数据,顺序排列的二进制UUID,在索引大小,表大小,查询时间等都有优势。当时Pecona的建议是,在数据库里写个函数,把UUID的顺序调整一下。而现在,我们可以在代码层面,更加轻松的做到这一点。
不要使用MySQL的UUID()函数生成UUID
MySQL的UUID()函数生成的UUID,貌似是V1版本的UUID,是无序的。
.NET的GUID同样不适合做主键
最后,再来讲一下.NET框架的GUID。微软的.NET框架自己搞了一个GUID,实际上它是在V4版本的UUID的基础上修改得到的。V4版本的UUID是大端顺序排列的,也被称为网络字节顺序。
但是GUID的字节顺序不同,采用了小端顺序排列。虽然比V4版本的UUID有改进,但是他依然不适合做主键的。除了字节顺序不同,GUID和V4版本的UUID字符串是完全相同的。
总结
不管是MySQL官方,还是负责制定UUID规范的IETF,还是PHP的一些类库作者,大家都看到了二进制UUID作为主键ID的未来发展潜力。我们不需要19位长度的长整型数字ID作为主键,就能实现类似的需求。
或许在不久的将来,这会成为事实上的标准,也说不定呢。
语言: zh-CN
翻译人员:
原作者:
转载地址:
源网址:
版权: 本站所有内容, 版权归原作者所有。发表原创内容将会获得现金奖励, 并且随着时间倍数增长, 请了解我们的内容奖励计划。