自增长id/UUID/雪花算法的深层次分析比较

说到id之前,先说一下mysql数据库的Innodb的主键索引,因为这和索引息息相关。

我们知道,在Innodb中,采用的是B+数索引。Innodb的存储结构,是聚簇索引。对于聚簇索引,

(1)顺序主键和随机主键的对效率的影响很大。我们分插入和查询来讲:

         插入。在磁盘中,有一个页的概念,而一页的容量是固定的,每一页按顺序存储数据,一般数据量达到一页的15/16,则开始存到下一页。但如果主键是随机的,那么每次插入之前,为了找到它的位置,首先需要进行一次比较,找到它的合适位置,再进行插入。如果是在页尾,那自然是最理想的效果。

      

UUID和自增长在程序中怎么实现此处不讲,我们直接从性能和实际使用来分析。

     说到性能,就不等不提到索引,此处以InnoDB的BTree索引来讲。

      uuid类型是varchar(36),而自增长Id则一般是bigInt类型。

      首先,大家要知道,id作为唯一索引,并不总是能提高效率。对于非常小的表,大部分情况下简单的全表扫描效率更高,对于中大型的表,索引才非常有效。因为索引帮助存储快速查找到记录的同时,也会带来额外的消耗。

       那么索引会带来哪些额外的消耗呢?空间和时间。

下面做了一个实验,在一个有足够内存容纳索引的服务器上插入100万条记录和300百万条记录,时间和空间上的消耗如下:

 

类型行数时间(秒)索引大小(MB)
自增长1000000137342
uuid1000000180544
自增长300000012331036
uuid300000045251707

        根据上面的结果,索引是会消耗额外的物理空间的,而聚簇索引消耗的物理空间更大。当数据特别多的时候,相对于bigInt类型的自增长Id,varchar(36)类型的uuid消耗的物理空间更为明显。

        在时间上,1)uuid由于占用的内存更大,所以查询、排序速度会相对较慢;2)在存储过程中,自增长id由于主键的值是顺序的,所以InnoDB把每一条记录都存储在上一条记录的后面。当达到页的最大填充因子时(innodb默认的最大填充因子为页大小的15/16,留出部分空间用于以后修改),下一条记录就会写入新的页面中。一旦数据按照这种方式加载,主键页就会被顺序的记录填满。而对于uuid,由于后面的值不一定比前面的值大,所以InnoDB并不能总是把新行插入的索引的后面,而是需要为新行寻找合适的位置(通常在已有行之间),并分配空间,这会增加额外的很多工作。这也是为什么当索引的列过长的时候,需要采用前缀索引,或者哈希索引了。

        尽管自增长id的优点这么多,但实际大型项目中却很少采用自增长id的,这是为什么呢?uuid几乎保证了不同数据库的不同表的id唯一,可以进行数据切分合并,而自增长id只能保证一个数据库中的一张表的id唯一,进行数据库合并的话并然会因主键冲突而失败,这是一个硬伤

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值