Databend 源码阅读: Storage 概要和 Read Partitions
作者:张祖前
Databend Labs 成员,数据库研发工程师
https://github.com/zhyass
❤️ 友情提示:代码演进较快,请注意文档的时效性哦!
引言
Databend 将存储引擎抽象成一个名为 Table
的接口,源码位于 query/catalog/src/table.rs
。
Table
接口定义了 read
、append
、alter
、optimize
、truncate
以及 recluster
等方法,负责数据的读写和变更。解释器(interpreter)通过调用 Table trait
的方法生成物理执行的 pipeline
。
通过实现 Table
接口的方法,可以定义 Databend 的存储引擎,不同的实现对应不同的引擎。
Storage 主要关注 Table
接口的具体实现,涉及表的元信息,索引信息的管理,以及与底层 IO 的交互。
目录
Read Partitions
以下以 fuse 引擎中 read partitions 的实现流程为例,简要分析 Storage 相关源码。
Partitions 的定义位于 query/catalog/src/plan/partition.rs
。
Table 接口中的 read_partitions
通过分析查询中的过滤条件,剪裁掉不需要的分区,返回可能满足条件的 Partitions。
Fuse 引擎会以 segment 为单位构建 lazy 类型的 FuseLazyPartInfo
。通过这种方式,prune_snapshot_blocks
可以下推到 pipeline 初始化阶段执行,特别是在分布式集群模式下,可以有效提高剪裁执行效率。
分区剪裁流程的实现位于 query/storages/fuse/src/pruning/fuse_pruner.rs
文件中,具体流程如下:
基于
push_downs
条件构造各类剪裁器(pruner),并实例化FusePruner
。调用
FusePruner
中的pruning
方法,创建max_concurrency
个分批剪裁任务。每个批次包括多个 segment 位置,首先根据internal_column_pruner
筛选出无需的 segments,再读取SegmentInfo
,并根据 segment 级别的MinMax
索引进行范围剪裁。读取过滤后的
SegmentInfo
中的BlockMetas
,并按照internal_column_pruner
、limit_pruner
、range_pruner
、bloom_pruner
、page_pruner
等算法的顺序,剔除无需的 blocks。执行
TopNPrunner
进行过滤,从而得到最终剪裁后的block_metas
。
剪裁结束后,以 Block 为单位构造 FusePartInfo
,生成 partitions
,接着调用 set_partitions
方法将 partitions
注入 QueryContext
的分区队列中。在执行任务时,可以通过 get_partition
方法从队列中取出。
Conclusion
Databend 的存储引擎设计采用了抽象接口的方式,具有高度的可扩展性,可以很方便地支持多种不同的存储引擎。Storage 模块的主要职责是实现 Table 接口的方法,其中 Fuse 引擎部分尤为关键。
通过对数据的并行处理,以及数据剪裁等手段,可以有效地提高数据的处理效率。鉴于篇幅限制,本文仅对读取分区的流程进行了简单阐述,更深入的解析将在后续的文章中逐步展开。
关于 Databend
Databend 是一款开源、弹性、低成本,基于对象存储也可以做实时分析的新式数仓。期待您的关注,一起探索云原生数仓解决方案,打造新一代开源 Data Cloud。
👨💻 Databend Cloud:databend.cn
📖 Databend 文档:databend.rs/
💻 Wechat:Databend
✨ GitHub:github.com/datafuselab…
版权声明: 本文为 InfoQ 作者【Databend】的原创文章。
原文链接:【http://xie.infoq.cn/article/26bc7e922c6a91310811310f9】。文章转载请联系作者。
评论