一篇文章读懂Doris

26 阅读5分钟

认识Doris

Doris是一个MPP架构的数据库,可以大规模并行处理。Doris 采用 MySQL 协议,高度兼容 MySQL 语法,支持标准 SQL。

Doris整体物理架构

截屏2026-01-20 12.19.35.png

1. 顶层:MySQL Tools (顾客下单区)

  • 图中的部分:最上方的蓝色框,显示支持 MySQL 协议。
  • 通俗理解:这是餐厅的前台窗口。顾客(开发人员或 BI 工具)不需要学新的点菜语言,直接用通俗的 MySQL 命令就能下单。Doris 对外伪装成一个普通的 MySQL,让你用起来非常顺手。

2. 中层:Frontend (FE - 经理办公室)

图中的 FE 分成了三种角色(Leader, Follower, Observer),它们是餐厅的管理层

  • Frontend (Leader/Follower) :这是值班经理

    • 它们负责接单(SQL 解析)、制定做菜计划(查询规划)、盯着库存(元数据管理)。
    • Leader 是大经理,说了算;Follower 是副经理,随时准备在大经理累倒时接班。它们之间通过日志同步信息,确保办公室里的账本(元数据)是一致的。
  • Frontend (Observer) :这是实习助理

    • 它们只看账本,不参与决策,专门负责回答那些简单的“查账”问题,帮经理分担压力,提高餐厅的接待速度。

3. 底层:Backend (BE - 后厨工人)

图中最下方的 Backend 框,标注着 C++ 编写。

  • 通俗理解:这是后厨的厨师们

    • C++ 编写:意味着它们干活极其麻利,动作极快(高性能)。
    • 分工协作:一个查询请求会被拆成很多小任务,分给多个 BE 同时开火。
    • 存储数据:食材(数据)就存在每个 BE 自己的冰箱(磁盘)里。
    • 横向通信:你看 BE 之间有箭头,这代表厨师们会互相传菜(Exchange 数据交换)。比如我这边的肉切好了,传给你去下锅炒。

一个query查询周期

截屏2026-01-20 12.18.51.png

图中数字步骤详解

1. Query (下单)

用户发送一条 SQL 给 Frontend简单理解为:顾客进店,跟店长说:“我要一份全店所有厨师做的红烧肉总和报告。”

2. Query Planner & Coordinator (制定计划与派发)

  • Planner:把 SQL 变成一堆 Fragment(小任务)。Coordinator:看哪个 BE 有数据,就把任务发给谁。
  • 简单理解为:店长算了一下,要把任务拆成:厨师 A 切肉,厨师 B 找调料,厨师 C 负责炖。然后把对应的指令(Fragment)发到各个厨房。

3. Fully MPP distributed (协同配合/数据交换)

这是图中最核心的部分, Exchange/Shuffle 发生的时刻。

  • 你会发现 Fragment 1-1, 1-2, 1-3 分布在不同的 BE 上。BE 之间有双向箭头。
  • 简单理解为:这就是“大规模并行处理”。每个厨师同时开火(并行)。如果厨师 A 切好了肉需要传给厨师 C 去炖,他们之间就会互相传菜(数据交换)。

4. Results (汇总结果)

各个 BE 完成了自己的任务,把局部的小结果传回给 Frontend简单理解为:厨师 A、B、C 各自把做好的部分端到店长面前。

5. Return results (交付)

FE 把所有局部结果做最后的合并(比如最后的求和),吐给用户。简单理解为:店长把所有的菜装进一个大盘子,递给顾客。

结合架构图和query生命周期图来整体分析一下

第一阶段:FE 层的“大脑指挥” (步骤 1-2)

  1. 建立连接:用户通过 MySQL 协议发送查询请求给 FE 的 MySQL Server

  2. SQL 解析与分析 (Parser & Analyzer) :FE 检查语法对不对,表 users 是否存在,用户有没有权限查看 score

  3. 生成逻辑计划 (Logical Plan) :FE 将 SQL 翻译成一棵由 ScanFilterAggregation 等算子组成的树。

  4. 生成物理计划与分布式拆解 (Optimizer & Planner)

    • FE 查看元数据 (Catalog) ,确定数据分布在哪些 Tablet 上,这些 Tablet 又在哪些 BE 上。
    • FE 将计划拆分成多个 Fragments(查询片段)。
  5. 任务派发 (Coordinator) :FE 将这些 Fragments 发送给相关的 BE 节点。


第二阶段:BE 层的“肌肉执行” (步骤 3)

此时,压力来到了各个 BE 节点。每个 BE 内部会发生以下动作:

  1. Pipeline 调度:BE 接收到 Fragment,Pipeline 执行引擎将其拆成流水线任务,分配给不同的 CPU 线程去跑。

  2. 定位数据(利用“眼睛”)

    • 列过滤:只打开 namescoreage 这几列的文件。
    • 索引过滤:利用 Zone Map (Max/Min) 跳过不符合 age > 18 的数据块。
    • 布隆过滤器:如果是精确匹配,则进一步“点杀”掉不需要的块。
  3. 数据读取 (Scan & Vectorized)ScanOperator 从磁盘(存算一体)或缓存/S3(存算分离)读取数据。数据以 Vector(向量化批次) 的形式推向后续算子,一次处理 1024 行,提升效率。

  4. 过滤与预计算 (Filter & Local Agg)

    • FilterOperator 剔除 age <= 18 的记录。
    • 本地聚合:BE 会先在自己本地算出“每个名字的分数总和”的中间结果。
  5. 数据交换 (Exchange/Shuffle) :如果需要全局聚合,BE 之间会通过网络互相传输中间结果。


第三阶段:汇总与返回 (步骤 4-5)

  1. 结果回传 (Results) :各 BE 完成计算后,将各自的最终结果(小结果集)发送回 FE 的 Coordinator
  2. FE 最终处理:FE 对来自各个 BE 的结果进行最后的简单汇总(例如把各 BE 传回的 SUM 再加一遍)。
  3. 返回客户端 (Return Results) :FE 通过 MySQL 协议将最终结果集打包发送给客户端用户。