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

Apache Doris 内部数据裁剪与过滤机制的实现原理


在分析型数据库的性能比拼中,“少做事” 往往比 “快做事” 更关键 —— 数据读取过程中的磁盘 IO、网络传输(尤其存算分离场景)是资源消耗的核心,而数据裁剪正是通过 “跳过不需要处理的数据”,从根源降低开销。

Apache Doris 作为面向实时分析的现代数据仓库,设计了多维度的数据裁剪与过滤机制,覆盖 “静态谓词过滤→动态场景优化(LIMIT/TopK/JOIN)” 全链路。本文将深入拆解这些机制的实现原理,带你理解 Doris 如何做到 “智能跳过无用数据”。

一、数据裁剪的价值

数据裁剪的核心逻辑是 “提前排除不符合条件的数据,减少后续计算的输入量”—— 对于 100TB 的原始数据,若能裁剪掉 99%,则后续计算只需处理 1TB,性能提升呈数量级增长。

行业内主流数据库已形成成熟的裁剪思路:

  • 静态裁剪:基于元数据或预计算信息过滤,如通过zone map(存储列的 min/max 值)、SMA(小物化聚合)跳过不满足谓词的分区 / 文件;
  • 动态裁剪:查询执行中生成过滤条件,如 Join 时用 Build 侧数据生成谓词过滤 Probe 侧;
  • 二级索引辅助:用 Bloom Filter、Cuckoo Filter等轻量级索引快速判断数据是否存在,避免全文件扫描。

Doris 的裁剪机制在吸收这些思路的基础上,结合自身 “MPP 架构 + 列存储 + 有序 Segment” 的特性,实现了更贴合实时分析场景的优化。

二、Doris 架构与数据存储:裁剪机制的基础

要理解裁剪逻辑,需先明确 Doris 的数据组织方式 —— 裁剪机制本质是 “利用数据存储的结构化特征,精准定位有用数据”。

2.1 整体架构:FE 决策 + BE 执行 + 存储层支撑

Doris 集群由三大组件协同:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • FE(Frontend):负责元数据管理(分区、表结构)、SQL 解析优化、裁剪策略规划(如分区列谓词过滤);
  • BE(Backend):执行数据扫描、计算,实现动态裁剪(如 LIMIT 停止读取、TopK 堆过滤);
  • 存储组件:本地 / 云端存储,以 “分区→分桶→Segment→列文件” 的层级存储数据,为裁剪提供元数据支持。

2.2 数据存储层级:从分区到列文件

Doris 的表按 “三级结构” 组织数据,每一层都为裁剪提供切入点:

  1. 分区(Partition):按分区键(如时间a)拆分,元数据记录每个分区的范围(如partition1: a<1partition2: 1≤a<2);
  2. 分桶(Bucket):每个分区按分桶键(如b)Hash 拆分,确保数据均匀分布;
  3. Segment:分桶的物理存储单位,每个 Segment 内数据按 Key 列(如a,b)有序排列,且包含:
  • 列文件:每列单独存储,文件头记录该列的 min/max、非空数等元数据;
  • 短键索引:快速定位 Key 列的行范围,避免全文件扫描。

2.3 数据裁剪的分类:静态与动态

Doris 按 “裁剪发生的时间” 将机制分为两类:

  • 静态裁剪:SQL 解析优化阶段确定,无需执行时计算,如 “a>0过滤p1分区”;
  • 动态裁剪:查询执行中根据实时数据生成过滤条件,如 LIMIT 到行数停止、TopK 用堆顶过滤数据。

具体可细分为四种核心机制:谓词静态过滤、LIMIT 动态裁剪、TopK 裁剪、JOIN 裁剪,下文逐一拆解。

三、谓词静态过滤:基于元数据的 “提前排除”

谓词静态过滤是 Doris 最基础也最高效的裁剪方式,通过 “FE 解析 SQL 谓词 + 存储元数据比对”,在数据读取前就排除无用分区 / 文件 / 行,分为三类场景。

3.1 分区列谓词过滤:FE 层的 “元数据筛选”

核心逻辑:分区列的谓词(如a>0)由 FE 处理,通过查询分区元数据(每个分区的范围),直接跳过不满足条件的分区。

以 SQL SELECT * FROM tbl WHERE a>0为例:

  1. FE 读取分区元数据:p1a<1)、p21≤a<2)、p32≤a<3);
  2. 比对谓词a>0p1包含a<1的部分数据(如a=-1)不满足,但p1整体范围与a>0有交集(如a=0.5),因此不跳过p1p2p3完全满足,全部保留;
  3. FE 仅将p1p2p3的读取任务下发给 BE,无需处理不存在的分区(如a≥3)。

优势:完全在 FE 层完成,无需 BE 参与,是开销最小的裁剪方式。

3.2 Key 列谓词过滤:Segment 内的 “范围定位”

核心逻辑:Key 列(如b)在 Segment 内有序存储,通过谓词生成 Key 列的上下界,用二分查找确定需读取的行范围,跳过范围外的数据。

以 SQL SELECT * FROM tbl WHERE b>0为例(b是 Key 列):

  1. BE 读取目标 Segment 的 Key 列(a,b)有序数据,假设某 Segment 的b值为[-2, -1, 1, 2, 3]
  2. 谓词b>0的下界是0,通过二分查找定位到第一个满足条件的行(b=1,行号 1);
  3. BE 仅读取行号≥1 的数据,跳过前两行(b=-2,-1),减少 50% 的行读取量。

3.3 普通列谓词过滤:列文件的 “元数据预筛”

核心逻辑:普通列(如c)的列文件头记录该列的 min/max 值,BE 先比对 min/max 与谓词,跳过不满足的列文件;对满足的列文件,读取后计算谓词,得到符合条件的行号,再读取其他列的对应行。

以 SQL SELECT * FROM tbl WHERE c>2为例(c是普通列):

  1. BE 扫描目标 Segment 的c列文件:
  • 列文件 0 的 min=0、max=1,小于谓词下界2,直接跳过该文件;
  • 列文件 1 的 min=1、max=5,与谓词有交集,读取该文件的c值;
  1. 对列文件 1 的c值(如[1,3,4,2,5])计算谓词,得到符合条件的行号(1,2,4);
  2. BE 仅读取其他列(a,b)的行号 1,2,4 的数据,避免读取全量行。

优势:通过列文件元数据提前排除无用文件,减少磁盘 IO;列存储特性确保仅读取需处理的列,进一步降低开销。

四、LIMIT 动态裁剪:“见好就收” 的读取策略

LIMIT 查询的核心需求是 “获取前 N 行数据”,Doris 通过 “提前停止数据读取” 避免无用计算,分两种场景优化。

4.1 Scan 节点的 LIMIT 裁剪:单并发 + 即时停止

场景:当 LIMIT 直接作用于 Scan 节点(如SELECT * FROM tbl LIMIT 100),Doris 会:

  1. 将 Scan 节点的并发度设为 1(默认并发为 BE 核心数);
  2. 当读取的数据行数达到 LIMIT 值(如 100 行),立即停止扫描,不再读取后续数据。

:若表中有 10 万行数据,LIMIT 100 时,BE 读取 100 行后就停止,仅处理 0.1% 的数据。

4.2 非 Scan 节点的 LIMIT 裁剪:停止上游数据传输

场景:当 LIMIT 作用于后续节点(如SELECT SUM(c) FROM tbl GROUP BY b LIMIT 100),Doris 会:

  1. 下游 LIMIT 节点实时统计接收的结果行数;
  2. 当行数达到 LIMIT 值,立即向上游节点(如 GROUP BY 节点)发送 “停止信号”;
  3. 上游节点收到信号后,停止向 LIMIT 节点传输数据,同时停止自身的计算。

核心:从下游反向触发上游停止,避免 “上游计算完所有结果,下游只取前 N 行” 的资源浪费。

五、TopK 裁剪:BI 场景的 “精准筛选”

TopK 查询(如 “取 GMV 前 10 的商品”)是 BI 分析的高频场景,传统做法是 “全量排序后取前 K”,开销极大。Doris 通过 “局部裁剪 + 全局汇总” 的两阶段策略,大幅减少数据处理量。

5.1 标准堆排序的局限

传统 TopK 用 “最小堆”(降序排序):扫描所有数据,插入堆中(堆大小为 K),最终堆中数据即为 TopK。但问题是 “必须扫描全量数据”,若数据量达 10 亿行,堆操作的开销依然巨大。

5.2 Doris 的两阶段 TopK 裁剪

Doris 利用 “Segment 内 Key 列有序” 和 “分布式计算” 特性,将 TopK 拆分为 “局部裁剪” 和 “全局裁剪”:

阶段 1:局部裁剪(每个 BE 扫描节点)
  1. 每个扫描节点维护一个大小为 K 的最小堆(如 K=10);
  2. 扫描数据时,将每行插入堆中:
  • 若堆未满(不足 10 行),直接插入;
  • 若堆满,比较当前行与堆顶(堆中最小的 TopK 元素):若当前行更大,替换堆顶并调整堆;若更小,直接丢弃;
  1. 扫描过程中,用 “堆顶元素” 作为动态过滤条件:后续数据若小于堆顶,直接跳过(无需插入堆),进一步减少堆操作。
阶段 2:全局裁剪(FE / 协调节点)
  1. 所有扫描节点将局部 TopK(最多 K 行 / 节点)发送给协调节点;
  2. 协调节点对所有局部 TopK 数据(共 N×K 行,N 为扫描节点数)构建新的最小堆,排序后取前 K 行,得到最终 TopK 结果;
  3. 若需返回 TopK 的完整列数据(如除排序列外的其他字段),协调节点将最终 TopK 的行号下发给 BE,BE 仅读取这些行号的完整数据。

:10 个 BE 节点,K=10,局部裁剪后仅需传输 100 行数据到全局节点,全局排序 100 行即可,相比全量排序 10 亿行,开销可忽略不计。

六、JOIN 裁剪:Hash Join 的 “前置过滤”

多表 Join 是数据库的耗时操作,Doris 通过 “在 Probe 侧读取前,用 Build 侧数据生成过滤谓词”,减少 Probe 侧的数据量,核心是 “自适应谓词生成” 和 “谓词等待策略”。

6.1 Hash Join 的基础逻辑

Hash Join 分为 Build 侧(小表)和 Probe 侧(大表):

  1. Build 侧:读取小表数据,构建 Hash Table(Key 为 Join 列,Value 为其他列);
  2. Probe 侧:读取大表数据,用 Join 列查询 Hash Table,匹配则输出结果。

裁剪的关键是 “Probe 侧只读取可能匹配 Build 侧的数据”—— 即通过 Build 侧的 Join 列值,生成过滤谓词,提前排除 Probe 侧的不匹配行。

6.2 自适应谓词生成:In 谓词 vs Bloom Filter

Doris 根据 Build 侧数据量,动态选择谓词类型:

  • 当 Build 侧去重后的数据量≤阈值(如 1000):生成In (v1, v2, ..., vn)谓词,Probe 侧用该谓词过滤,仅保留 Join 列在In列表中的行,过滤率 100%(无误判);

  • 当 Build 侧数据量 > 阈值:生成 Bloom Filter(布隆过滤器),Probe 侧用 Bloom Filter 判断 Join 列是否 “可能存在” 于 Build 侧:
    • 若 Bloom Filter 判断 “不存在”,直接跳过该行;
    • 若判断 “可能存在”,继续后续 Hash 查询(Bloom Filter 的误判会被 Hash 查询修正,不影响结果正确性)。

为什么用 Bloom Filter:当 Build 侧数据量极大(如 100 万行),生成 In 谓词的开销(存储、传输、解析)过高,而 Bloom Filter 体积小(如 100 万行仅需几 MB)、判断速度快,虽有误判但不影响正确性。

6.3 谓词等待策略:平衡延迟与效率

Bloom Filter/In 谓词的构建需要时间,若 Probe 侧一直等待,会增加查询延迟。Doris 采用 “1 秒等待策略”:

  1. Probe 侧启动后,先等待 1 秒,若 Build 侧的谓词已生成,立即用谓词过滤;
  2. 若 1 秒内未收到谓词,Probe 侧直接开始读取数据(避免无限等待);
  3. 后续若谓词生成完成,Probe 侧立即启用谓词,过滤剩余数据。

:Build 侧构建 Bloom Filter 需 2 秒,Probe 侧前 1 秒读取的数据未过滤,但 1 秒后启用 Bloom Filter,过滤后续 80% 的数据,整体仍能大幅减少 Join 开销。

七、总结

Doris 的四类数据裁剪机制,覆盖了从 “静态元数据筛选” 到 “动态执行优化” 的全链路,未来,Doris 社区将持续探索更通用的裁剪策略。

对于开发者而言,理解这些裁剪机制不仅能更好地编写高效 SQL(如优先用分区列 / Key 列做过滤),也能在排查性能问题时(如慢查询),快速定位 “是否因裁剪未生效导致全量扫描”—— 毕竟,在分析型数据库中,“不处理数据” 才是最快的处理方式。

http://www.dtcms.com/a/426770.html

相关文章:

  • 专业做网站流程小程序开发步骤大全
  • C语言基础之指针2
  • 淘客网站怎么做 知乎wordpress淘宝联盟插件
  • flink工作流程
  • openHarmony之storage_daemon:分区挂载与设备节点管理机制讲解
  • 建站怎么赚钱个人官方网站怎么建设
  • 学习笔记093——Windows系统如何定时备份远程服务器的mysql文件到本地?
  • 操作系统内核架构深度解析:从单内核、微内核到鸿蒙分布式设计
  • MySQL 架构全景解析
  • .NET MVC中实现后台商品列表功能
  • oracle logwr,ckpt,dbwn 如何协同工作的
  • C# 网络通讯核心知识点笔记
  • Ubuntu之apt安装ClickHouse数据库
  • 在线音乐网站开发现状网站全屏弹出窗口
  • 泛型在Java集合框架中的应用有哪些?
  • 服务器中使用Docker部署前端项目
  • mysql之二进制日志
  • 【完整源码+数据集+部署教程】染色体图像分割系统: yolov8-seg-KernelWarehouse
  • Docker MySQL 使用全流程
  • Visual Studio主题、字体、快捷键、开发环境设置,自用
  • 火山 19 混音伴音 接口
  • Bean精细化控制属性序列化反序列化
  • 前端权限模型——RBAC
  • 杭州知名网站建设公司电商网站建设好么
  • 不忘初心网站建设做网站的工具
  • VSCode实现字符串粘贴转义复制反转义
  • 第2章 三个小工具的编写(2)
  • 【DeepResearch】langgraph自主迭代研究能力的 AI 代理及分析
  • 专题:2025医药行业数智赋能与AI应用全景研究报告|附200+份报告PDF、数据仪表盘汇总下载
  • Alibaba Cloud Linux 3 +Docker 部署 ThinkPHP6 (宝塔环境)-问题篇