当前位置: 首页 > news >正文

Merge-On-Write 的处理流程

简单来讲,Merge-On-Write 的处理流程是:

  1. 对于每一条 Key,查找它在 Base 数据中的位置(rowsetid + segmentid + 行号)

  2. 如果 Key 存在,则将该行数据标记删除。标记删除的信息记录在 Delete Bitmap 中,其中每个 Segment 都有一个对应的 Delete Bitmap

  3. 将更新的数据写入新的 Rowset 中,完成事务,让新数据可见(能够被查询到)

  4. 查询时,读取 Delete Bitmap,将被标记删除的行过滤掉,只返回有效的数据

关键问题

设计适合 Doris 的 Merge-On-Write 方案,需要重点解决以下几个问题:

  1. 导入时如何高效定位到是否存在需要被标记删除的旧数据?

  2. 标记删除的信息如何进行高效的存储?

  3. 查询阶段如何高效的使用标记删除的信息来过滤数据?

  4. 能否实现多版本支持?

  5. 如何避免并发导入的事务冲突,导入与 Compaction 的写冲突?

  6. 方案引入的额外内存消耗是否合理?

  7. 写入代价导致的写入性能下降是否在可接受范围内?

根据以上关键问题,我们进行了一系列优化措施,使得以上问题得到较好的解决。  文中我们将进行详细介绍:

主键索引

由于 Doris 是面向大规模分析设计的列存系统,并没有主键索引的能力,因此为了能够快速定位到有没有要覆盖的主键,以及要覆盖的主键的行号,就需要给 Doris 增加一个主键索引

我们采取了如下的优化措施:

  1. 为每个 Segment 维护一个主键索引。主键索引的实现采用了似于 RocksDB Partitioned Index 的方案。该方案能够实现非常高的查询 QPS,同时基于文件的索引方案也能够节省内存占用。

  2. 为每个 Segment 维护一个主键索引对应的 Bloom Filter。当 Bloom Filter 命中时才会查询主键索引。

  3. 为每个 Segment 记录一个主键的区间范围 [min-key, max-key]

  4. 维护一个纯内存的区间树,使用所有 Segment 的主键区间构造。在查询一个主键时,无需遍历所有的 Segment,可以通过区间树定位到可能包含该主键的 Segment,大幅减少需要查询的索引量 

  5. 对于命中的所有 Segment,按照版本从高到低进行查询。在 Doris 中高版本意味着更新的数据,因此如果一个主键在高版本的 Segment 索引中命中,就无需继续查询更低版本的 Segment 。

查询单个主键的流程如下图所示:

Delete Bitmap

Delete Bitmap 采取多版本的方式进行记录,具体如下图所示:

  • 图中的 Segment 文件是由版本 5 的导入产生的,包含了该 Tablet 中版本 5 的导入数据

  • 版本 6 的导入中包含了对主键 B 的更新,因此会在 Bitmap 中将第二行标记删除,并在 DeleteBitmap 中记录版本 6 的导入对该 Segment 的修改

  • 版本 7 的导入包含了对主键 A 的更新,也会产生一个对应版本的 Bitmap;同理版本 8 的导入也会产生一个对应的 Bitmap

所有的 Delete Bitmap 存储在一个大的 Map 中,每次导入都会将最新的 Delete Bitmap 序列化到 RocksDB 中。其中关键定义如下:

using SegmentId = uint32_t;
using Version = uint64_t;
using BitmapKey = std::tuple<RowsetId, SegmentId, Version>;
std::map<BitmapKey, roaring::Roaring> delete_bitmap;

每个 Rowset 中的每个 Segment,都会记录多个版本的 Bitmap。Version 为 x 的 Bitmap 意味着版本为 x 的导入对当前 Segment 的修改。

多版本 Delete Bitmap 的优点:

  1. 能很好的支持多版本的查询,例如版本 7 的导入完成后,一个该表的查询开始执行,会使用 Version 7 来执行,即使这个查询执行时间较长,在查询执行期间版本 8 的导入已经完成,也无需担心读到版本 8 的数据(或者漏掉被版本 8 删除的数据)

  2. 能够很好的支持复杂的 Schema Change。在 Doris 中,复杂的 Schema Change(例如类型转换)需要先进行双写,同时将某个版本之前的历史数据进行转换后再删除掉旧版的数据。多版本的 Delete Bitmap 可以很好的支持当前的 Schema Change 实现

  3. 可以支持数据拷贝和副本修复时的多版本需求

相关文章:

  • 网站开发系统调研目的/周口seo公司
  • wordpress load.php/关键词排名查询工具有什么作用?
  • 如何申请一个免费的网站空间/高端网站建设哪个好
  • 优速网站建设/百度网盘官方
  • 支持ipv6网站开发/网络营销专业怎么样
  • 网站怎么推广运营/高端网站设计公司
  • Java和vue开发的橱柜定制系统家具定制系统
  • 智能巡检系统:企业安全生产管理的智能助手
  • 【NumPy 数组过滤、NumPy 中的随机数、NumPy ufuncs】
  • AtCoder Beginner Contest 282(python3)
  • Word处理控件Aspose.Words功能演示:在 Java 中将 DOC 或 DOCX 转换为 JPG
  • 2023 目标,与君共勉
  • Dockerfile介绍及常用保留指令
  • 四、网络层(四)IPv6
  • 【Pycharm教程】在 PyCharm 中使用 Emacs 作为外部编辑器
  • 笔试训练(5)
  • MySQL数据库的安装、创建库、创建表、创建测试数据及连接取数
  • MySQL索引-索引的分类