Databend 源码阅读: Storage 概况和 Read Partitions

news2024/11/28 22:53:31

作者:zhyass | Databend Labs 成员,数据库研发工程师

❤️ 友情提示:代码演进较快,请注意文档的时效性哦!

引言

Databend 将存储引擎抽象成一个名为 Table 的接口,源码位于 query/catalog/src/table.rs

Table 接口定义了 readappendalteroptimizetruncate 以及 recluster 等方法,负责数据的读写和变更。解释器(interpreter)通过调用 Table trait 的方法生成物理执行的 pipeline

通过实现 Table 接口的方法,可以定义 Databend 的存储引擎,不同的实现对应不同的引擎。

Storage 主要关注 Table 接口的具体实现,涉及表的元信息,索引信息的管理,以及与底层 IO 的交互。

目录

包名作用
common/cache定义与管理缓存,包括磁盘缓存和内存缓存。类型包含表 meta 缓存、查询结果缓存、表数据缓存等。
common/index定义与使用索引,目前支持 bloom filter index、page index、range index。
common/locks管理与使用锁,支持表级别的锁。
common/pruner分区剪裁算法,包括 internal column pruner、limiter pruner、page pruner、topn pruner、range pruner。
common/table_meta表 meta 的数据结构定义。
hivehive 表的交互
icebergiceberg 交互
information_schema、system系统表定义
memory、null、random用于开发和测试的引擎
view视图相关
stagestage 数据源的读取
parquet把 parquet 文件作为数据源
fusefuse 引擎模块
fuse/src/iotable meta、index、block 的读写 IO 交互
fuse/src/pruningfuse 分区裁剪
fuse/src/statisticscolumn statistics 和 cluster statistics 等统计信息
fuse/src/table_functionstable function 实现
fuse/src/operationfuse 引擎对 table trait 方法的具体实现。并包含了如 ReadSource、CommitSink 等 processor 算子的定义

Read Partitions

以下以 fuse 引擎中 read partitions 的实现流程为例,简要分析 Storage 相关源码。

Partitions 的定义位于 query/catalog/src/plan/partition.rs

pub struct Partitions {
    // partitions 的分发类型。
    pub kind: PartitionsShuffleKind,
    // 一组实现了 PartInfo 接口的 partition,
    pub partitions: Vec<PartInfoPtr>,
    // partitions 是否为 lazy。
    pub is_lazy: bool,
}

Table 接口中的 read_partitions 通过分析查询中的过滤条件,剪裁掉不需要的分区,返回可能满足条件的 Partitions。

#[async_trait::async_trait]
impl Table for FuseTable {
    #[minitrace::trace]
    #[async_backtrace::framed]
    async fn read_partitions(
        &self,
        ctx: Arc<dyn TableContext>,
        push_downs: Option<PushDownInfo>,
        dry_run: bool,
    ) -> Result<(PartStatistics, Partitions)> {
        self.do_read_partitions(ctx, push_downs, dry_run).await
    }
}

Fuse 引擎会以 segment 为单位构建 lazy 类型的 FuseLazyPartInfo。通过这种方式,prune_snapshot_blocks 可以下推到 pipeline 初始化阶段执行,特别是在分布式集群模式下,可以有效提高剪裁执行效率。

pub struct FuseLazyPartInfo {
    // segment 在 snapshot 中的索引位置。
    pub segment_index: usize,
    pub segment_location: Location,
}

分区剪裁流程的实现位于 query/storages/fuse/src/pruning/fuse_pruner.rs 文件中,具体流程如下:

  1. 基于 push_downs 条件构造各类剪裁器(pruner),并实例化 FusePruner
  2. 调用 FusePruner 中的 pruning 方法,创建 max_concurrency 个分批剪裁任务。每个批次包括多个 segment 位置,首先根据 internal_column_pruner 筛选出无需的 segments,再读取 SegmentInfo,并根据 segment 级别的 MinMax 索引进行范围剪裁。
  3. 读取过滤后的 SegmentInfo 中的 BlockMetas,并按照 internal_column_prunerlimit_prunerrange_prunerbloom_prunerpage_pruner 等算法的顺序,剔除无需的 blocks。
  4. 执行 TopNPrunner 进行过滤,从而得到最终剪裁后的 block_metas
pub struct FusePruner {
    max_concurrency: usize,
    pub table_schema: TableSchemaRef,
    pub pruning_ctx: Arc<PruningContext>,
    pub push_down: Option<PushDownInfo>,
    pub inverse_range_index: Option<RangeIndex>,
    pub deleted_segments: Vec<DeletedSegmentInfo>,
}

pub struct PruningContext {
    pub limit_pruner: Arc<dyn Limiter + Send + Sync>,
    pub range_pruner: Arc<dyn RangePruner + Send + Sync>,
    pub bloom_pruner: Option<Arc<dyn BloomPruner + Send + Sync>>,
    pub page_pruner: Arc<dyn PagePruner + Send + Sync>,
    pub internal_column_pruner: Option<Arc<InternalColumnPruner>>,
    // Other Fields ...
}

impl FusePruner {
    pub async fn pruning(
        &mut self,
        mut segment_locs: Vec<SegmentLocation>,
        delete_pruning: bool,
    ) -> Result<Vec<(BlockMetaIndex, Arc<BlockMeta>)>> {
        ...
    }
}

剪裁结束后,以 Block 为单位构造 FusePartInfo,生成 partitions,接着调用 set_partitions 方法将 partitions 注入 QueryContext 的分区队列中。在执行任务时,可以通过 get_partition 方法从队列中取出。

pub struct FusePartInfo {
    pub location: String, 
    pub create_on: Option<DateTime<Utc>>,
    pub nums_rows: usize,
    pub columns_meta: HashMap<ColumnId, ColumnMeta>,
    pub compression: Compression,
    pub sort_min_max: Option<(Scalar, Scalar)>,
    pub block_meta_index: Option<BlockMetaIndex>,
}

Conclusion

Databend 的存储引擎设计采用了抽象接口的方式,具有高度的可扩展性,可以很方便地支持多种不同的存储引擎。Storage 模块的主要职责是实现 Table 接口的方法,其中 Fuse 引擎部分尤为关键。

通过对数据的并行处理,以及数据剪裁等手段,可以有效地提高数据的处理效率。鉴于篇幅限制,本文仅对读取分区的流程进行了简单阐述,更深入的解析将在后续的文章中逐步展开。

关于 Databend

Databend 是一款开源、弹性、低成本,基于对象存储也可以做实时分析的新式数仓。期待您的关注,一起探索云原生数仓解决方案,打造新一代开源 Data Cloud。

👨‍💻‍ Databend Cloud:databend.cn

📖 Databend 文档:databend.rs/

💻 Wechat:Databend

✨ GitHub:github.com/datafuselab…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1216064.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023年9月 少儿编程 中国电子学会图形化编程等级考试Scratch编程一级真题解析(选择题)

2023年9月scratch编程等级考试一级真题 选择题&#xff08;共25题&#xff0c;每题2分&#xff0c;共50分&#xff09; 1、下列哪项内容是不可以修改的 A、角色名称 B、造型名称 C、背景名称 D、舞台名称 答案&#xff1a;D 考点分析&#xff1a;考查scratch相关知识&am…

centos搭建docker镜像Harbor仓库的简明方法

在kubernetes集群中如果要部署springcloud这样的应用&#xff0c;就必须有一个自建的docker镜像中心仓库。 它的目的有两点&#xff1a; 1. 镜像拉取速度快 2. 开发好维护 而Harbor是一个非常好用的docker本地仓库 所以本篇文章来讲讲如何在部署Harbor仓库 首先系统版本最…

tegra nvidia agx xaiver 系统开机自动启动风扇配置方法

确保系统可以连接到互联网&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 1.更新系统软件源&#xff1a; sudo apt-get update2.安装pip工具 sudo apt-get install python-pip3.安装nvidia对应工具 sudo -H pip install jetson-stats4.打开NVI…

华为eNSP综合实验考试

VLAN信息表 设备名称 端口 链路类型 VLAN 参数 HZ-HZCampus-Agg01-S5731 GE0/0/1 Trunk PVID:1 Allow-pass&#xff1a;10 20 Eth-trunk1&#xff08;GE0/0/2,0/0/3,0/0/23&#xff09; Trunk PVID:1 Allow-pass&#xff1a;10 20 GE0/0/24 Access PVID&#xf…

Leetcode 33 搜索旋转排序数组

class Solution {//旋转数组从中间分开&#xff0c;总有一侧是有序的&#xff0c;一侧是无序的//只需要判断是否在有序区间就可以进行二分查找public int search(int[] nums, int target) {int left 0, right nums.length - 1;while(left < right){int mid (left right)…

小红书直播开启新纪元,拓世法宝AI直播一体机助您轻松成为行业标杆!

2023年&#xff0c;小红书终于成功坐上了电商牌桌。 今年3月的“董洁效应”带动了一批品牌商家、博主入驻小红书试水&#xff0c;其直播业务积蓄了巨大势能。10月15日&#xff0c;“初代名媛”章小蕙完成了在小红书的第二场直播&#xff0c;以销售额破亿的成绩打响了小红书双1…

Chrome开发者模式去除时间轴

经常用chrome调试&#xff0c;发现时间轴用的不多&#xff0c;想屏蔽掉。 参考&#xff1a;滑动验证页面 我做了截图记录下

众安保险面试题

文章目录 1.说一下Java内存模型?2.List、Set、Map的区别?3.介绍一下设计模式?4.MySQL存储结构?5.索引失效的场景?6.为什么使用函数索引会失效?7.Spring事务有哪两种?7.1 编程式事务@RestController7.2 声明式事务8.@Transactional实现原理?9.事务如何合并@Transactiona…

卡码网语言基础课 | 12. 位置互换

通过本次练习&#xff0c;将要学习到以下C知识点&#xff1a; 位置互换交换变量字符串 题目&#xff1a;给定一个长度为偶数位的字符串&#xff0c;请编程实现字符串的奇偶位互换。 奇偶位互换是指字符串的奇数位和偶数位相互交换位置 即&#xff1a;第一位和第二位交换&…

服装供应链管理的革新利器—超高频RFID技术

一、行业概述 服装行业一直被视为低技术含量的劳动密集型产业&#xff0c;但实际上&#xff0c;科学技术在整个行业的发展中起着至关重要的作用&#xff0c;从服装面料的制作到服装设计、生产制作、物流到终端销售&#xff0c;科技力量贯穿于每一个环节。然而&#xff0c;传统…

城市生命线丨城市燃气管网监测系统功能效果

11月6日&#xff0c;福建泉州某小区发生煤气闪爆导致1死三伤&#xff0c;这起事故再次为我们敲响了城市燃气管网安全监测的警钟。在城市生命线的建设中&#xff0c;城市燃气管网监测系统以其独特的作用和价值&#xff0c;成为保障城市安全的重要一环。 根据应急管理部《全国城镇…

Flex布局---看一篇就够了

1. flex布局是什么&#xff1f; flex是flexible Box的缩写&#xff0c;用来为盒装模型提供的最大的灵活性&#xff0c;任何一个容器都可以指定为flex布局。Flex布局称为flex容器&#xff0c;所有的子元素为容器成员Flex项目&#xff08;flex item&#xff09;&#xff1b; 当为…

ES7升级、jar包升级、工具类封装,代码改造

一、spring-data-elasticsearch 引入es版本适配 二、jar升级 在项目工程根pom.xml文件中增加maven依赖管理在这里插入图片描述 <properties><elasticsearch.spring.version>4.2.0</elasticsearch.spring.version><elasticsearch.version>7.12.0</e…

JS-项目实战-更新水果单价更新小计更新总计

1、fruit.js //当页面加载完成后执行后面的匿名函数 window.onload function () {//get:获取 Element:元素 By:通过...方式//getElementById()根据id值获取某元素let fruitTbl document.getElementById("fruit_tbl");//table.rows:获取这个表格的所有的行&a…

echarts点击事件、柱状图设置区间颜色

实现echarts柱状图标记区域&#xff0c;并在单击柱状条时触发点击事件切换标记区域 //html <div id"main" style"width: 600px;height:400px;"></div>//js let _chart null; letselectInfo {};//选择的柱状条信息&#xff0c;可用于信息的获…

【iDRAC】突破错误信息壁垒,利用iDRAC提高效率

序 面对旧服务器上的黄色警示灯&#xff0c;工作人员往往陷入困惑。更糟糕的是&#xff0c;如果该服务器转手多次&#xff0c;缺少root用户密码和IP地址&#xff0c;那么要访问服务器iDRAC就更困难了。但是出现问题的硬件蕴含着重要信息&#xff0c;为了解开这个谜团&#xff…

Linux Docker图形化工具Portainer如何进行远程访问?

文章目录 前言1. 部署Portainer2. 本地访问Portainer3. Linux 安装cpolar4. 配置Portainer 公网访问地址5. 公网远程访问Portainer6. 固定Portainer公网地址 前言 Portainer 是一个轻量级的容器管理工具&#xff0c;可以通过 Web 界面对 Docker 容器进行管理和监控。它提供了可…

【教3妹学编程-算法题】最大化数组末位元素的最少操作次数

3妹&#xff1a;“太阳当空照&#xff0c;花儿对我笑&#xff0c;小鸟说早早早&#xff0c;你为什么背上炸药包” 2哥 :3妹&#xff0c;什么事呀这么开发。 3妹&#xff1a;2哥你看今天的天气多好啊&#xff0c;阳光明媚、万里无云、秋高气爽&#xff0c;适合秋游。 2哥&#x…

群晖7.2版本套件安装CloudDriver2

CloudDrive是一个强大的多云盘管理工具&#xff0c;为用户提供包含云盘本地挂载的一站式的多云盘解决方案。挂载到本地后&#xff0c;可以像本地文件一样进行操作。 一、套件库添加矿神源 二、安装CloudDriver2 1、搜索安装 搜索框输入【clouddrive】&#xff0c;搜索到Clou…