背景
新公司数据库的表都用的varchar作为主键,且使用的雪花ID。因为我之前公司没有用varchar作为主键的情况,旧公司使用的bigint的自增。所以对于varchar + 雪花ID的方案不太熟悉。
问题
其中比较疑惑的是varchar的mysql索引排序规则是怎么样的,如果使用雪花ID(纯数字)字符串。是否还像bigint自增那样,对于主键索引(聚簇索引)增加节点(记录)都能在最新索引的数据页的末尾添加。 否则的话,每次添加都不同程度的对索引进行重排插入的效率会非常低且消耗性能。
案例
下面是以varchar类型的主键例子
分析
当插入记录的时候,Mysql字符串排序的比较
1.如果按照数字的大小来比较 1100706681013 < 1314621806366078。绝对出现索引树节点的索引重排。性能堪忧
2.然后思考,雪花ID自增应该不影响。那么不清晰的点就在于Mysql对于varchar类型索引排序规则
3.参考其他博客发现Mysql的varchar排序如下
原因是varchar排序并不是简单的比大小,它是一个字符一个字符进行比较排序
比如11和101首先要比较各自第一个字符1和1,当两个字符相同的时候比较第二个字符,1和0进行比较,0比1小所以101要排在前面,其它的字符就不用再比较。 01和11同理,第一个字符0和1进行比较,0比1小所以01这个个数值要排在前面。
4.为什么不用Long作为雪花ID的存储类型呢?因为前端Js的number存储最大值9007199254740992 (2 的 53次方 -1),而long的最大值9223372036854775807。前端会有精度丢失,然后和后端的ID对不上的问题。当然也可以通过Java代码来转行,可是这样做的代价还不如直接数据库用varchar
总结
雪花ID + varchar类型主键不会特别影响插入性能。但是varchar相对占用更大内存空间,查询的时候恐怕跨页查询会比bigint自增的方案占用内存多一点,稍微有点性能损耗。但是对于解决公司的数据量大需要使用分库的情况是个不错的方案。