Doris 的批量更新

doris的更新特指对于unique类型的表,对于这种类型的表,如果insert的记录与已有的记录的unique key相同,也相当于update。

doris无论是什么类型的表,都是追加方式修改、增加数据的。

一个insert或update语句就是一次导出,会被一个事务包起来保护,也会生成一个segment文件,无论什么类型的表,无论一个insert插入多么少的数据,都会新增一个segment文件,而不是在已有的segment文件中增加数据。

就是说,如果频繁执行小数据量的insert就会产生非常多的很小的segment文件。

可见doris的设计是为了一次大批量的导入的,而多次小批量导入效率是不高的。

doris BE的update流程调试起来比较麻烦,是因为线程较多(因为许多操作是异步操作的,许多对象的操作是由各自的线程来做,它们之间的数据传递是通过带锁的消息队列),许多调用不是一个线程完成,而且多个线程合作完成,调用栈是一个线程的,但是许多调用函数不在一个线程中执行。

我对doris批量更新原理的理解如下:

1、只有 unique 类型的表支持更新操作,insert 和 update 底层本质上是一样的,insert 时 unique key 冲突时,就是update,本质上doris只有导入和查询两种操作。

2、更新操作,底层实现,就是先生成新数据,并写入新的segment文件,旧数据的segment文件不会修改,但被更新的记录标记删除,每个segment有一个delete-bitmap对象,标记哪些记录被删除,delete-bitmap不存储在segment文件中,而是存储在同一个BE节点的rocksdb中,这是个内嵌在BE代码中的key-value数据库。

更新时,旧的数据文件不会被修改,只是增加新的segment文件和delete-bitmap信息,效率是很高的。

3、读取时,参考每个segment的delete-bitmap,判断记录被删除则忽略,如果同一个unique key的记录被多次更新,每次更新都会生成不同的segment和对应的delete-bitmap,读取时都要参考(称为merge操作),最终返回的是最后一次更新的数据。

4、一条insert或update语句算是一次导入,即使只包括一条记录,也会生成一个segment文件并写到磁盘,并且之后不会修改或向其中追加数据,下一次insert或update会创建新的segment文件。

可见,doris是为了一次大批量的导入/更新设计的,小批量多次的导入(insert/update)会产生大量的小segment文件,效率很低。

5、BE内有线程会定期做 compaction,把若干小的segment文件(属于同一个tablet)合并成一个大的新segment,并且,此时物理删除之前被标记删除的行数据,同时删除rocksdb中对应的delete-bitmap,以后查询时要做的工作就少多了。

6、有了上面的认知,可以看到,doris的批量更新操作就是导入操作,效率与导入操作差不多,只是更新时多了查询旧数据和记录delete-bitmap操作,并且把一些垃圾回收工作推后,交给了异步的compaction线程,这降低了写入时的工作量,提高了写入的速度,对读取速度影响也比较小。(其它数据库,是导入时把所有该做的都做完了,然后报告结束,而doris是导入时仅仅完成最必要的部分,然后报告结束,还有一部分工作推迟给compation做)

7、还有一些细节,例如:两阶段提交和与FE的交互、线程池还没有细看,我没有形成思维模型。

参考:

10x 查询性能提升,全新 Unique Key 的设计与实现|新特性解读 (qq.com)

Doris原理分享(1) - 知乎

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值