MPP(Massively Parallel Processing,大规模并行处理)是目前大数据分析引擎最主流的架构形态。

无论是开源的 Apache Doris,还是阿里云的 Hologres,底层走的都是"MPP + 列式存储 + 向量化执行"这套技术路线。

本文以 Apache DorisHologres 为例,系统梳理 MPP 架构的核心思想、主要特性,以及存储计算分离、向量化执行(SIMD)、行列存储这几个关键技术点。


什么是 MPP

MPP 是一种 Shared-Nothing(无共享) 的并行计算架构:

与之对比的是传统架构:

架构存储扩展方式典型系统
SMP(对称多处理)共享内存单机加 CPU传统单机数据库
Shared-Disk共享存储加节点但存储争抢Oracle RAC
MPP(Shared-Nothing)各节点独立存储加节点线性扩展Doris、Hologres、ClickHouse、Greenplum

三种架构的差异,本质上是**“共享什么、不共享什么”**的问题。下面用三张图分别示意它们的资源布局与扩展路径。

SMP:单机共享内存

所有 CPU 通过共享总线访问同一份内存与磁盘,多核之间天然数据一致,但内存带宽和总线是竞争瓶颈。

D2 Diagram
qtopie.github.io

Shared-Disk:共享存储集群

计算节点各自拥有 CPU 与内存,但访问同一份共享存储。好处是数据只有一份、易做高可用,代价是节点间要频繁协调缓存一致性,存储 I/O 成为争抢点(典型如 Oracle RAC)。

D2 Diagram
qtopie.github.io

MPP:Shared-Nothing 无共享

每个节点拥有独立的 CPU、内存与磁盘,数据水平分片到各节点,计算在本地进行、只交换中间结果,因此加节点就能线性扩展。

D2 Diagram
qtopie.github.io

三种架构的演进脉络也很清晰:SMP 靠加 CPU 解决单机算力 → Shared-Disk 把存储抽出来做多机高可用 → MPP 把存储也打散,用无共享换取线性扩展。而 MPP 的核心价值正是**“分而治之”**:把一个大查询切碎成小任务并行执行,同时数据在本地读取,最大程度减少网络传输,从而实现"算得越多、加机器越快"的线性扩展能力。对比 SMP 与 Shared-Disk,MPP 的每个节点都自带存储、自给自足,节点之间几乎不需要交换大块数据。

MPP 的查询执行流程

以 Apache Doris 为例,它的经典架构是 FE + BE 两层

一条 SQL 的执行路径大致是:客户端提交 SQL → FE 解析并生成分布式执行计划 → 将子计划分发到多个 BE → 各 BE 并行读取本地数据分区 → 通过 Exchange 节点做中间结果交换与聚合 → 最终结果返回客户端。

D2 Diagram
qtopie.github.io

Hologres 的架构思路与之一致:前端节点(FGM / Frontend Service Manager)负责元数据与查询入口,Worker 节点构成无状态的共享计算集群并行执行查询。

为什么能并行计算?

“分而治之"听起来很朴素,但一个更根本的问题是:计算为什么能被拆开并行?如果扫描的数据量很大,还能并行吗?

答案藏在三个层次的设计里:数据分片、算子级并行、流水线执行

数据分片:把"读"也并行起来

MPP 数据库在数据写入时,就把表按照 Hash / Range 策略物理打散到各节点的本地磁盘上。查询时,每个节点只扫描自己本地的那一份数据,节点之间没有任何共享状态,也就不需要跨节点协调、加锁或等待。这也是前面反复强调的 Shared-Nothing 的真正含义——“并行"不是执行时临时想出来的,而是从数据布局开始就是为并行而设计的。

D2 Diagram
qtopie.github.io

那么,如果扫描的数据量很大,还能并行吗?能,而且数据量越大越能体现并行价值。关键在两点:

算子层面:天生就是并行的

在数据分片之上,并行还体现在算子设计上。现代 MPP 数据库的查询计划是一棵算子树(DAG):Scan、Filter、Aggregate、Join 等算子会被实例化成多个并行执行单元,分布到不同节点、不同 CPU 核上同时运行。节点之间通过 Exchange 算子(Shuffle / 广播)交换中间结果,保证数据能正确汇集到需要它的算子那里。

这里要区分两种执行模型——它们决定了"为什么 MPP 能实时、MapReduce 偏串行”:

D2 Diagram
qtopie.github.io

所以,“ODPS 等离线计算是部分是串行的"这个直觉是对的:它每个阶段内部是并行的,但阶段之间是串行的——屏障 + 落盘保证了批处理的最大吞吐和容错性(任务失败可重跑),代价是延迟被拉高到分钟甚至小时级。而 MPP 把整条执行链打通成流水线,算子级并行 + 数据流式传递,这正是毫秒级响应的根源。

MPP 数据库的主要特性

以 Doris 与 Hologres 为代表的现代 MPP 分析数据库,通常具备以下特性:

存储与计算分离

早期 MPP 数据库(如 Greenplum、早期 Doris)采用存储与计算耦合的架构:数据固定在本地磁盘,扩容必须搬运数据,缩容则浪费计算资源,成本和弹性都不理想。

云原生时代,存算分离(Storage-Compute Separation) 成为主流演进方向:

D2 Diagram
qtopie.github.io

需要说明的是,Doris 经历了从"本地多副本"到"存算分离"的演进:Doris 3.x 起提供存算分离部署模式,数据落到对象存储,计算与存储解耦;Hologres 则天生为云而设计,底层即为共享存储架构。两者的差异主要体现在落地形态上,思想殊途同归。

向量化执行与 SIMD

传统数据库(如 MySQL、PostgreSQL)基于 Volcano / 迭代器模型逐行处理数据:每一行都要经过一层层算子(Scan → Filter → Project → Join → Aggregate)的虚函数调用,CPU 开销大、分支预测失败率高、指令流水线利用率低。

向量化执行(Vectorized Execution) 的核心思路是:按列、按批次(Batch)处理数据,每次批量处理 N 行(如 1024 行),一次性对整列数据做运算。它的优势在于:

D2 Diagram
qtopie.github.io

这里再补充几点:

行列混合存储

行存与列存的核心差异在于数据的组织与访问粒度

D2 Diagram
qtopie.github.io

在实际系统中,“行存"与"列存"并非非此即彼:

Apache Doris 与 Hologres 对比

维度Apache DorisHologres
定位开源 MPP 分析型数据库(OLAP)阿里云 Serverless 在线分析数仓(OLAP)
架构FE(无状态)+ BE(计算存储一体)共享计算集群 + 共享存储(云原生)
存算分离3.x 支持存算分离模式(对象存储)原生存算分离,计算与存储独立伸缩
向量化执行全链路向量化,SIMD 深度优化内置向量化执行引擎
存储格式列式为主,多种表模型列存为主,支持行存与行列混合
实时写入支持高频实时导入(Stream Load)支持实时写入,面向流式数据
生态Apache 开源,社区活跃,Multi-Catalog 联邦查询阿里云生态,与 MaxCompute、Flink 深度集成
部署形态自建 / 私有化 / 云托管纯云上 Serverless

实时数仓:MPP 之上的时效性补充

传统的离线数仓以 Hive、Spark 为代表的 T+1 批处理为主,数据从产生到可分析往往滞后一天。而业务对时效性的要求不断提高,催生了"实时数仓”:把数据的采集、加工与分析链条压缩到分钟级甚至秒级,让分析结果尽可能贴近业务发生的当下。

从技术形态上看,实时数仓通常涉及两条路径:

所以,实时数仓并非一种全新的架构,而是在 MPP 并行分析引擎之上补齐了"实时数据接入"这一环。理解了 MPP 的并行执行、列式存储与向量化执行,也就掌握了实时数仓分析侧的核心底座。

为什么 Hologres 能做实时数仓,而 ODPS 不行?

同样是阿里云的大数据产品,ODPS(MaxCompute)查询慢且不能实时,而 Hologres 能做到毫秒级响应,根本原因在于两者设计目标和底层架构的截然不同。

简单来说:ODPS 是为"存"和"粗加工"海量数据而设计的重型武器,而 Hologres 是为"查"和"快用"数据而生的轻骑兵

🐘 ODPS (MaxCompute):为什么它不擅长实时?

ODPS 的核心目标是高吞吐、低成本地处理海量(PB 级)数据。它面向离线批处理场景,而不是低延迟的在线查询。

尽管 ODPS 慢,但它依然是数据加工链路中不可或缺的一环,因为它能以极低成本存储和处理海量历史数据。

🚀 Hologres:为什么它能做到实时?

Hologres 是专为实时交互式分析设计的 MPP 架构数据仓库,目标是毫秒级响应

⚔️ MPP vs. MapReduce:核心差异对比

ODPS(基于 MapReduce)和 Hologres(基于 MPP)代表了两种不同的分布式计算思想,以下是它们的核心区别:

特性维度MPP (如 Hologres)MapReduce (如 ODPS)
设计目标低延迟的交互式分析(OLAP)高吞吐的批量数据处理
计算模式全并行,所有节点同时计算,实时返回结果分阶段(Map, Shuffle, Reduce),串行执行
数据交互节点间高效通信,数据流动少大量数据落盘和网络传输(Shuffle 阶段)
查询延迟毫秒/秒级(亚秒级)分钟/小时级
典型场景实时报表、即席查询(Ad Hoc)、在线数据服务海量数据 ETL、数据清洗、离线数仓建设
资源调度查询级别,按需分配,响应快作业级别,依赖集群调度器,有排队延迟
适用数据结构化、需要快速响应的热数据结构化、半结构化、非结构化的海量冷数据

💎 总结

两者并非替代关系,而是协同工作的理想拍档:ODPS 负责低成本地存储和加工海量数据,而 Hologres 则负责对加工后的数据进行极速、实时的查询与服务

深入原理:Hologres 的 HSAP 架构、查询引擎与存储引擎

前面从"设计目标"层面解释了 Hologres 为什么能实时。这一节再往下挖一层,结合 Hologres 官方技术揭秘(查询引擎、存储引擎、核心架构三篇文章),看看它在架构、执行引擎和存储引擎三个层面分别是怎么设计出来的。

HSAP:为什么"一套系统"能同时做服务和分析?

Hologres 的定位是 HSAP(Hybrid Serving & Analytical Processing,服务分析一体化):同一份数据、同一套系统,既要支撑高 QPS 的在线查询(Serving,如点查、接口服务),又要支撑复杂的离线分析(Analytical,如多维聚合、BI 报表)。

为什么需要这种设计?传统方案各有痛点:

Lambda 架构:实时数仓出现前的"标准答案”

在 HSAP 出现之前,业界对"既要实时、又要全量准确"的标准解法是 Lambda 架构:把一条数据链路拆成两条,各取所长。

D2 Diagram
qtopie.github.io

Lambda 架构由三层组成:

听起来很合理,但落地时问题不少:

HSAP 的核心思想是统一数据存储 + 统一查询服务:实时数据和离线数据落进同一份存储,服务和分析走同一个 SQL 接口,避免数据搬运与多份拷贝。

D2 Diagram
qtopie.github.io

这套架构的关键是存储计算分离:数据全部存放在分布式文件系统(盘古 / HDFS)中,Backend 计算节点无状态、可弹性扩缩容。计算负载上来就加计算节点,数据增长就扩存储,互不阻塞。底层还提炼了 HOS(HoloOS) 异步无锁框架,保证高并发下 CPU 多核的高利用率。

查询引擎:异步 DAG + 分布式执行计划

Hologres 的执行引擎是完全自研的,而不是在开源引擎上做改造。为什么?文章给出的理由是:传统 MPP 引擎支持通用 SQL 但对实时场景优化不足;Druid、ClickHouse 这类专为实时场景设计的引擎,单表查询快但复杂查询(多表 Join)性能差。Hologres 的目标是两者兼得。

它的核心设计有四点:

一句话总结查询引擎的思路:分布式执行计划切分到数据所在节点,全异步流水线把每个 CPU 核都喂满,向量化把单核吞吐榨干。这也呼应了前面"为什么能并行计算"一节:并行不是执行时临时拼出来的,而是从数据分片、算子设计到调度模型,整套都是为并行而生的。

存储引擎:LSM 写入路径与多版本读

Hologres 的存储引擎采用 LSM(Log-Structured Merge) 技术,写入路径是典型的"先写日志,再写内存表,最后刷盘合并":

D2 Diagram
qtopie.github.io

这一设计带来了三个关键能力:

存储上还支持行存 / 列存两种格式:行存适合主键点查(Serving 场景),列存适合大范围扫描聚合(Analytical 场景)。主键约束(Primary Key)通过行存实现去重,两种格式读写接口统一,用户建表时指定即可。文件内部还支持字典索引(提高字符串处理效率与压缩比)和位图索引(高效过滤),配合 Block Cache(LRU/LFU 淘汰)进一步加速读路径。

小结:把前面所有线索串起来

把这一节和前面几节放在一起看,Hologres 的"实时"能力是层层叠加出来的:

层面解决什么问题关键技术
架构弹性与统一存储计算分离、HSAP 一体化、HOS 异步框架
执行引擎查询快分布式执行计划 + 全异步 DAG + 向量化 + 延迟物化
存储引擎写入快且实时可见LSM 顺序写、WAL、写入即读、多版本快照读
在线服务高并发点查行存 + 主键索引 + Block Cache,百万级 QPS

这也解释了为什么 Hologres 能在双十一顶住 5.96 亿/秒的实时写入、单表 2.5PB、99.99% 的查询 80ms 内返回——不是某一项技术单点突破,而是从存储、执行到调度的全链路为"实时 + 高并发 + 分析"三种诉求统一设计的结果

没有银弹:Hologres 的缺点与不适合的场景

前面铺垫了大量 Hologres 的优势,但没有银弹。它的"实时快"是一系列设计取舍换来的,代价同样明显。理解缺点与边界,比记住优点更重要——选型不是找"最好的引擎",而是匹配 workload。

缺点与代价

不适合的场景

场景为什么不适合更合适的选择
海量冷数据长期存储存储成本爆炸OSS / ODPS
超大表全量 Join 计算shuffle 瓶颈 + 数据倾斜Spark / Presto
高频小粒度事务写入更新与删除代价高MySQL / PolarDB
超高并发在线 KV 点查杀鸡用牛刀,成本高Redis / Tair
全文检索 / 非结构化数据结构化分析型引擎Elasticsearch
需要自主可控、免厂商锁定闭源绑定云生态Doris / ClickHouse

选型建议

Hologres 把所有资源押在"热数据 + 高并发分析"这一件事上,所以它快;代价是贵、吃内存、Join 与倾斜敏感、闭源锁定。适合它的典型场景是:实时报表、即席分析、在线数据服务,且数据量在可承受的成本范围内。而数据仓库的完整链路(海量存储、复杂 ETL、深度数据挖掘)仍然需要 ODPS、Spark 等引擎配合——各司其职,才是合理的架构

小结

MPP 架构的底层逻辑其实很朴素:数据拆开、任务拆开、并行执行、结果合并。而现代 MPP 分析数据库之所以能把性能做到极致,靠的是几个关键技术的叠加:

理解了这条主线,再去看 Doris、Hologres、ClickHouse 等任何一款分析引擎,都能很快抓住其设计精髓。

参考链接