
MySQL
UUID或者雪花ID用作主键,乍一看很不错,可实际上存在诸多隐患,对于
MySQL这种相对娇弱的数据库引擎来说更是如此。下面咱们从底层源码的角度来剖析一下。首先要清楚,InnoDB引擎中的主键是聚簇索引,这就意味着主键的顺序直接影响着数据在磁盘上的存储顺序。它期望我们提供递增、有序的主键,这样在写入数据时能够顺序向后添加,效率很高。要是突然采用UUID,这就完全打乱了这个逻辑。UUID本身是随机生成的,数据会到处插入,导致存储页频繁拆分,数据分布得极为分散,写入性能就会大幅下降。更为糟糕的是,随机的ID还会使缓存命中率降低。
MySQL有个buffer pool,简单来讲,它的作用就是把常用的数据页缓存到内存里,从而减少磁盘I/O。但由于UUID让数据页的分布过于随机,每次查询都要到不同的地方查找,缓存命中率就会急剧下降。久而久之,内存使用率降低,I/O增加,系统性能就会变差。另外,不得不提及UUID或者雪花ID的长度问题。UUID通常为128位,雪花ID为64位,这比传统的32位或者64位自增整型ID要长得多。主键变长了,索引自然也跟着变长,索引文件占用的空间就更多,查询时需要扫描更多的索引页,性能也就会变差。也许有人会问:那我把它改成无序的二级索引可以吗?可以是可以,但这只是治标不治本,聚簇索引的问题没有得到解决,磁盘碎片和页分裂的问题依然存在。举个简单的例子,下面是使用UUID做主键的建表语句:然后插入几条数据:看起来好像没什么问题,但在大数据量的场景下,就会发现性能很快下降,尤其是查询和写入操作增多的时候。那么雪花ID?虽然它是有序的,但这种有序性是基于时间戳的,分布并不完全均匀。例如,如果在同一秒内生成大量的ID,还是会出现页分裂的问题。总结UUID和雪花ID在一些分布式系统或者需要全球唯一ID的场景下很好用,但不要用来做数据库主键,特别是在
MySQL中。若想要高效的读写性能,自增ID永远是最佳选择。给大家分享一个很棒的编程导航网站,里面有大量免费教程可供学习: