Doris分布式查询引擎深度解析:从MPP架构到Pipeline执行的高效查询实践
|
🌺The Begin🌺点点关注,收藏不迷路🌺
|
01 引言:什么是分布式查询引擎?
在传统数据库中,查询执行受限于单机的CPU和内存资源,面对PB级数据时往往力不从心。分布式查询引擎的出现,正是为了解决这一难题——它将一个复杂的查询任务拆解成多个子任务,分发到集群中的多台机器上并行执行,最后将结果汇总返回。
Apache Doris作为一款高性能的MPP(Massively Parallel Processing,大规模并行处理)分析型数据库,其分布式查询引擎融合了现代数据库的多项前沿技术:从基于成本的查询优化器(CBO),到充分利用多核CPU的Pipeline执行引擎,再到针对高并发点查场景的短路径优化。
本文将系统性地解析Doris分布式查询引擎的核心架构、关键技术原理,并通过实战案例展示如何利用这些技术实现高效的数据查询。
02 Doris分布式查询引擎全景架构
2.1 MPP架构概览
Doris的查询引擎采用典型的MPP架构,将查询任务并行分散到多个节点上执行,每个节点负责一部分数据的处理,最后将结果汇总。
2.2 三层执行计划结构
Doris的执行计划分为三个层次,这种分层设计是实现分布式并行执行的基础:
| 层级 | 名称 | 说明 |
|---|---|---|
| PLAN | 执行计划 | 一个SQL被翻译成的完整执行计划 |
| FRAGMENT | 执行片段 | 单机执行的最小单元,多个Fragment组成完整PLAN |
| PLAN NODE | 算子 | 执行计划的最小单位,如ScanNode、JoinNode、AggNode |
03 Pipeline执行引擎:多核CPU的充分利用
3.1 从火山模型到Pipeline模型
Doris 3.0之后,Pipeline执行引擎彻底替换了传统的火山模型(Volcano Model)。火山模型中,每个算子通过next()函数逐行拉取数据,这种"一行一行"的处理方式导致大量虚函数调用和CPU缓存未命中。
Pipeline执行引擎的核心改进:
- 批量处理:一次处理一批数据(通常4096行),减少函数调用次数
- 流水线并行:将算子拆分为Pipeline,多个PipelineTask并行执行
- 线程可控:限制查询线程数量,避免线程膨胀
3.2 Pipeline核心概念
Pipeline:由一个SourceOperator和一个SinkOperator及中间的多个Operator组成。
- SourceOperator:从外部读取数据(表或Exchange Buffer)
- SinkOperator:输出数据(网络Shuffle或HashTable)
PipelineTask:Pipeline的实例化执行单元。同一个Pipeline可生成多个PipelineTask,每个Task处理不同的数据分片,实现并行处理。
Dependency机制:Pipeline之间存在依赖关系。例如Join的Build端必须先完成,Probe端才能开始执行。Dependency机制负责协调这种执行顺序。
3.3 并行扫描(Parallel Scan)
扫描数据是IO密集型操作,Doris的ScanOperator通过动态生成多个Scanner实现并行扫描:
Scanner机制:
- 每个Scanner扫描100万-200万行数据
- Scanner完成数据解压、过滤等计算任务
- 数据发送到DataQueue供ScanOperator读取
- 有效避免分桶不合理或数据倾斜导致的性能瓶颈
3.4 Local Shuffle:解决数据倾斜
数据倾斜是分布式查询的常见问题。Doris通过Local Exchange机制,在本地将数据重新分发,解决执行过程中的数据倾斜。
工作原理:
- 在Pipeline中插入Local Exchange,将其拆分为上下游
- 通过HASH或Round Robin方式将数据均匀分发到下游Task
- 有效将(1,1,7)的数据分布变为(3,3,3)
04 Runtime Filter:动态过滤优化
Runtime Filter是Doris查询优化的一项核心技术,它根据Join运行时生成的动态信息,提前过滤数据,大幅减少IO和网络传输。
4.1 工作原理
以订单表(1亿行)和客户表(10万行)的Join为例:
SELECT COUNT(*)
FROM orders JOIN customer ON o_custkey = c_custkey
WHERE c_nation = "china";
关键步骤:
- 执行
c_nation="china"过滤,得到参与Join的c_custkey集合(约4000个) - Join Build端根据这些key生成Runtime Filter(Bloom Filter或IN Filter)
- Runtime Filter下推给orders表的Scan节点
- Scan节点利用Filter提前过滤数据,1亿行减少到40万行
4.2 Runtime Filter类型
| 类型 | 适用场景 | 特点 |
|---|---|---|
| IN Filter | 小数据集(<1024个值) | 精确过滤,效果好 |
| Bloom Filter | 中等数据集 | 内存占用可配置,有假阳性 |
| Min/Max Filter | 有序数据列 | 内存占用小,适合范围过滤 |
4.3 查看Runtime Filter
通过EXPLAIN命令查看Runtime Filter的生成和应用情况:
EXPLAIN SELECT COUNT(*) FROM orders JOIN customer ON o_custkey=c_custkey;
执行计划中会显示:
| runtime filters: RF000[bloom] <- c_custkey -- Join端生成
| runtime filters: RF000[bloom] -> o_custkey -- Scan端应用
05 高并发点查优化
对于主键等值查询场景,Doris 2.0+版本提供了专门的高并发点查优化路径。
5.1 短路径优化(Short-Circuit)
传统查询需要经过完整的SQL解析、优化、计划生成流程,对于点查来说开销太大。短路径优化直接绕过这些步骤:
启用条件:
- 建表时开启
"enable_unique_key_merge_on_write" = "true" - 开启
"store_row_column" = "true"(或Doris 3.0后用row_store_columns指定部分列) - 查询条件仅包含主键等值条件
-- 建表开启点查优化
CREATE TABLE tbl_point_query (
k1 INT NULL,
v1 VARCHAR(30) NULL
) UNIQUE KEY(k1)
DISTRIBUTED BY HASH(k1) BUCKETS 1
PROPERTIES (
"enable_unique_key_merge_on_write" = "true",
"store_row_column" = "true"
);
-- 点查自动走短路径
SELECT * FROM tbl_point_query WHERE k1 = 123;
5.2 PreparedStatement缓存
当CPU成为点查瓶颈时,可以使用PreparedStatement将SQL解析结果缓存:
// JDBC示例
String url = "jdbc:mysql://127.0.0.1:9030/db?useServerPrepStmts=true";
PreparedStatement stmt = conn.prepareStatement("SELECT * FROM t WHERE k1 = ?");
stmt.setInt(1, 1234);
ResultSet rs = stmt.executeQuery();
性能提升:开启PreparedStatement后,点查性能可提升4倍以上。
5.3 验证优化生效
通过EXPLAIN验证短路径是否生效,执行计划中应出现SHORT-CIRCUIT标识。
06 查询优化器:CBO+RBO混合优化
Doris的查询优化器采用基于代价的优化(CBO)和基于规则的优化(RBO)相结合的策略。
6.1 核心优化技术
6.2 统计信息收集
CBO依赖准确的统计信息来评估执行计划的代价:
| 统计信息 | 说明 | 作用 |
|---|---|---|
| 表大小 | 行数、数据量 | 评估扫描代价 |
| 列基数 | DISTINCT值数量 | 判断过滤效果 |
| 列NULL比例 | NULL值占比 | 影响Join和过滤 |
| 数据分布 | 直方图 | 精确估算选择率 |
-- 手动收集统计信息
ANALYZE TABLE table_name;
-- 查看统计信息
SHOW STATS table_name;
07 高效查询最佳实践
7.1 执行计划分析
使用EXPLAIN分析查询执行计划是性能调优的第一步:
-- 查看执行计划
EXPLAIN SELECT * FROM orders WHERE order_date = '2024-01-01';
-- 查看详细计划(含预估行数、数据量)
EXPLAIN VERBOSE SELECT * FROM orders WHERE order_date = '2024-01-01';
-- 查看Profile分析实际执行
SET enable_profile = true;
SELECT ...;
SHOW QUERY PROFILE;
7.2 关键指标解读
| 指标 | 含义 | 优化方向 |
|---|---|---|
PREAGGREGATION: ON | 命中物化视图 | 聚合已被预计算,性能好 |
partitions=N/M | 扫描分区数 | N应远小于M,检查分区裁剪 |
SHORT-CIRCUIT | 走点查短路径 | 主键点查已优化 |
runtime filters | Runtime Filter生效 | Join自动优化 |
7.3 查询优化检查清单
08 总结
Apache Doris的分布式查询引擎通过多层次的优化技术,实现了高效的数据查询能力:
| 技术组件 | 核心作用 | 关键特性 |
|---|---|---|
| MPP架构 | 并行计算基础 | Fragment切分、数据Shuffle |
| Pipeline引擎 | 多核CPU利用 | PipelineTask并行、Local Shuffle |
| Runtime Filter | 动态数据过滤 | Join场景下提前过滤数据 |
| CBO+RBO优化器 | 执行计划优化 | 谓词下推、Join重排序 |
| 点查优化 | 高并发主键查询 | 短路径、行存、PreparedStatement |
核心要点回顾:
- MPP架构是并行计算的基础:将查询拆分为多个Fragment,分布到多节点并行执行
- Pipeline引擎充分利用多核CPU:PipelineTask并行执行,Local Shuffle解决数据倾斜
- Runtime Filter动态过滤数据:根据Join运行时信息生成过滤条件,减少IO和传输
- 点查优化应对高并发场景:短路径+行存+PreparedStatement,性能提升4倍以上
- 执行计划分析是调优起点:使用EXPLAIN分析,识别瓶颈,针对性优化
通过理解这些核心技术原理,开发者可以更好地利用Doris的分布式查询能力,在实际业务中实现高效的数据分析。

|
🌺The End🌺点点关注,收藏不迷路🌺
|
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/qq_41840843/article/details/159615736




