认识Doris
Doris是一个MPP架构的数据库,可以大规模并行处理。Doris 采用 MySQL 协议,高度兼容 MySQL 语法,支持标准 SQL。
Doris整体物理架构
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查询周期
图中数字步骤详解
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)
-
建立连接:用户通过 MySQL 协议发送查询请求给 FE 的 MySQL Server。
-
SQL 解析与分析 (Parser & Analyzer) :FE 检查语法对不对,表
users是否存在,用户有没有权限查看score列 -
生成逻辑计划 (Logical Plan) :FE 将 SQL 翻译成一棵由
Scan、Filter、Aggregation等算子组成的树。 -
生成物理计划与分布式拆解 (Optimizer & Planner) :
- FE 查看元数据 (Catalog) ,确定数据分布在哪些 Tablet 上,这些 Tablet 又在哪些 BE 上。
- FE 将计划拆分成多个 Fragments(查询片段)。
-
任务派发 (Coordinator) :FE 将这些 Fragments 发送给相关的 BE 节点。
第二阶段:BE 层的“肌肉执行” (步骤 3)
此时,压力来到了各个 BE 节点。每个 BE 内部会发生以下动作:
-
Pipeline 调度:BE 接收到 Fragment,Pipeline 执行引擎将其拆成流水线任务,分配给不同的 CPU 线程去跑。
-
定位数据(利用“眼睛”) :
- 列过滤:只打开
name、score、age这几列的文件。 - 索引过滤:利用 Zone Map (Max/Min) 跳过不符合
age > 18的数据块。 - 布隆过滤器:如果是精确匹配,则进一步“点杀”掉不需要的块。
- 列过滤:只打开
-
数据读取 (Scan & Vectorized) :
ScanOperator从磁盘(存算一体)或缓存/S3(存算分离)读取数据。数据以 Vector(向量化批次) 的形式推向后续算子,一次处理 1024 行,提升效率。 -
过滤与预计算 (Filter & Local Agg) :
FilterOperator剔除age <= 18的记录。- 本地聚合:BE 会先在自己本地算出“每个名字的分数总和”的中间结果。
-
数据交换 (Exchange/Shuffle) :如果需要全局聚合,BE 之间会通过网络互相传输中间结果。
第三阶段:汇总与返回 (步骤 4-5)
- 结果回传 (Results) :各 BE 完成计算后,将各自的最终结果(小结果集)发送回 FE 的 Coordinator。
- FE 最终处理:FE 对来自各个 BE 的结果进行最后的简单汇总(例如把各 BE 传回的
SUM再加一遍)。 - 返回客户端 (Return Results) :FE 通过 MySQL 协议将最终结果集打包发送给客户端用户。