问题
记得刚接手项目时,看了下项目里的库表结构,发现表主键都是varchar(36),就问研发,为啥搞个这么长的主键?研发说这个主键是通过java 程序产生的UUID,考虑到以后数据分片不会产生重复。考虑的还是挺周到!但这么长字段做主键也有许多问题:
- 首先这个主键很长,而主键会自动添加在每一二级索引的后面,这样会导致数据冗余严重,特别是二级索引建多了的情况下,有时会导致索引的数据比表的数据还大!
- 其次,这样产生UUID是无序的,导致插入性能很差。因为当插入一个数据到B+tree时,系统将这个数据插入到一个合适的位置,这会导致多次IO,而如果数据本身是自增的,那么系统只须将它添加的B+Tree的末端即可,效率要高的多。
因此我还是建议使用整型+auto_increment, 虽然MySQLauto_increment有个众所周知的、历史悠久的bug(这个bug终于在MySQL8的到修复,MySQL8中auto_increment将会被写入redo log 中啦,爽歪歪),但大多数情况下还是可靠的,并且MySQL官方也建议使用auto_incremnet做主键。但它也有问题,就是无法适应数据分片的扩容(分库分表),除非你之前规划的非常好。
MySQL8中的解决方案
如今MySQL8 中对UUID提供了增强性支持,不仅使其长度大大缩小,而且解决了顺序的问题!(我之所以称之为增强性支持,是因为他们提供了两个内置函数做了转换,感觉这种方式有点儿low,这样的函数我们也可以写啊)
大家都知道,UUID是由32位16进制字符串组成(不算分隔符’-‘)如: