MPP(Massively Parallel Processing,大规模并行处理)是目前大数据分析引擎最主流的架构形态。
无论是开源的 Apache Doris,还是阿里云的 Hologres,底层走的都是"MPP + 列式存储 + 向量化执行"这套技术路线。
本文以 Apache Doris 和 Hologres 为例,系统梳理 MPP 架构的核心思想、主要特性,以及存储计算分离、向量化执行(SIMD)、行列存储这几个关键技术点。
什么是 MPP
MPP 是一种 Shared-Nothing(无共享) 的并行计算架构:
- 每个节点独立自治:每个计算节点拥有独立的 CPU、内存、磁盘和操作系统,节点之间不共享资源。
- 数据水平分片:表数据按 Hash、Range 等方式切分成多个分区,均匀分布在所有节点上,每个节点只负责自己那部分数据。
- 计算本地化:查询任务被拆分成多个子计划,分发到各个节点并行执行,每个节点先做"本地计算",再通过节点间数据交换(Shuffle / Exchange)汇聚结果。
与之对比的是传统架构:
| 架构 | 存储 | 扩展方式 | 典型系统 |
|---|---|---|---|
| SMP(对称多处理) | 共享内存 | 单机加 CPU | 传统单机数据库 |
| Shared-Disk | 共享存储 | 加节点但存储争抢 | Oracle RAC |
| MPP(Shared-Nothing) | 各节点独立存储 | 加节点线性扩展 | Doris、Hologres、ClickHouse、Greenplum |
三种架构的差异,本质上是**“共享什么、不共享什么”**的问题。下面用三张图分别示意它们的资源布局与扩展路径。
SMP:单机共享内存
所有 CPU 通过共享总线访问同一份内存与磁盘,多核之间天然数据一致,但内存带宽和总线是竞争瓶颈。
Shared-Disk:共享存储集群
计算节点各自拥有 CPU 与内存,但访问同一份共享存储。好处是数据只有一份、易做高可用,代价是节点间要频繁协调缓存一致性,存储 I/O 成为争抢点(典型如 Oracle RAC)。
MPP:Shared-Nothing 无共享
每个节点拥有独立的 CPU、内存与磁盘,数据水平分片到各节点,计算在本地进行、只交换中间结果,因此加节点就能线性扩展。
三种架构的演进脉络也很清晰:SMP 靠加 CPU 解决单机算力 → Shared-Disk 把存储抽出来做多机高可用 → MPP 把存储也打散,用无共享换取线性扩展。而 MPP 的核心价值正是**“分而治之”**:把一个大查询切碎成小任务并行执行,同时数据在本地读取,最大程度减少网络传输,从而实现"算得越多、加机器越快"的线性扩展能力。对比 SMP 与 Shared-Disk,MPP 的每个节点都自带存储、自给自足,节点之间几乎不需要交换大块数据。
MPP 的查询执行流程
以 Apache Doris 为例,它的经典架构是 FE + BE 两层:
- FE(Frontend):负责 SQL 解析、查询规划(Query Plan)、执行调度、元数据管理与查询优化。它是集群的"大脑",无状态、可水平扩展。
- BE(Backend):负责数据存储与查询计划的实际执行。BE 之间采用 Shared-Nothing 架构,各自管理本地数据分片。
一条 SQL 的执行路径大致是:客户端提交 SQL → FE 解析并生成分布式执行计划 → 将子计划分发到多个 BE → 各 BE 并行读取本地数据分区 → 通过 Exchange 节点做中间结果交换与聚合 → 最终结果返回客户端。
Hologres 的架构思路与之一致:前端节点(FGM / Frontend Service Manager)负责元数据与查询入口,Worker 节点构成无状态的共享计算集群并行执行查询。
为什么能并行计算?
“分而治之"听起来很朴素,但一个更根本的问题是:计算为什么能被拆开并行?如果扫描的数据量很大,还能并行吗?
答案藏在三个层次的设计里:数据分片、算子级并行、流水线执行。
数据分片:把"读"也并行起来
MPP 数据库在数据写入时,就把表按照 Hash / Range 策略物理打散到各节点的本地磁盘上。查询时,每个节点只扫描自己本地的那一份数据,节点之间没有任何共享状态,也就不需要跨节点协调、加锁或等待。这也是前面反复强调的 Shared-Nothing 的真正含义——“并行"不是执行时临时想出来的,而是从数据布局开始就是为并行而设计的。
那么,如果扫描的数据量很大,还能并行吗?能,而且数据量越大越能体现并行价值。关键在两点:
- 并行度与数据量解耦:并行度由"分片数"决定,而分片数由"节点数 × 每节点分片数"决定。数据再多,也只是让每个分片更大、分片数量不变(甚至可以通过再分区增加分片数),每个节点的负担几乎不受影响。
- 每节点负担恒定:扫描 1 TB 和扫描 1 GB,只要节点数成比例增加,每个节点扫描的字节数可以完全一样——所以 MPP 才能做到"加节点、线性扩展”。
算子层面:天生就是并行的
在数据分片之上,并行还体现在算子设计上。现代 MPP 数据库的查询计划是一棵算子树(DAG):Scan、Filter、Aggregate、Join 等算子会被实例化成多个并行执行单元,分布到不同节点、不同 CPU 核上同时运行。节点之间通过 Exchange 算子(Shuffle / 广播)交换中间结果,保证数据能正确汇集到需要它的算子那里。
这里要区分两种执行模型——它们决定了"为什么 MPP 能实时、MapReduce 偏串行”:
- MPP(如 Doris / Hologres)采用流水线执行:Scan 边产出边交给 Filter,Filter 边过滤边交给 Aggregate,像"水管"一样边算边走。上游算子不需要等下游全部完成,中间结果尽量停留在内存中,不做落盘,因此延迟极低。
- MapReduce(如 ODPS)采用阶段化执行:一个查询被切成 Map → Shuffle → Reduce 多个阶段。阶段与阶段之间有一道同步屏障(Barrier)——必须等所有 Map 任务全部完成、中间结果落盘后,才能启动下一阶段。阶段内部是并行的,但阶段之间是串行的。
所以,“ODPS 等离线计算是部分是串行的"这个直觉是对的:它每个阶段内部是并行的,但阶段之间是串行的——屏障 + 落盘保证了批处理的最大吞吐和容错性(任务失败可重跑),代价是延迟被拉高到分钟甚至小时级。而 MPP 把整条执行链打通成流水线,算子级并行 + 数据流式传递,这正是毫秒级响应的根源。
MPP 数据库的主要特性
以 Doris 与 Hologres 为代表的现代 MPP 分析数据库,通常具备以下特性:
- 高性能并行查询:多节点多核并行扫描与计算,配合列式存储,TB 级数据秒级返回。
- 高压缩比:列式存储天然具备更好的数据局部性,配合字典、RLE、ZSTD、Snappy 等压缩算法,存储成本大幅降低。
- 向量化执行:批量处理数据并利用 CPU 的 SIMD 指令集做数据并行,突破"内存带宽"瓶颈。
- 物化视图(MV):预计算并固化高频聚合结果,查询时直接命中物化视图,加速响应。
- 高可用与副本机制:通过多副本(Replication)保证数据可靠性与故障自愈;Hologres 在共享存储之上可快速重建计算节点。
- 多表 Join 与复杂分析:支持星型/雪花模型下的多表 Join、窗口函数、近似分析。
- 联邦查询与多源接入:Doris 通过 Multi-Catalog 直接查询 MySQL、Hive、Iceberg 等外部数据;Hologres 也支持外部表与 MaxCompute 等联邦查询。
- 实时与批量一体(HTAP 方向):Doris 支持实时写入 + 高并发点查;Hologres 基于共享存储实现流式写入与在线分析的统一。
存储与计算分离
早期 MPP 数据库(如 Greenplum、早期 Doris)采用存储与计算耦合的架构:数据固定在本地磁盘,扩容必须搬运数据,缩容则浪费计算资源,成本和弹性都不理想。
云原生时代,存算分离(Storage-Compute Separation) 成为主流演进方向:
- 计算集群无状态:计算节点只负责查询执行,不持有持久化数据,可以秒级启停、按需扩缩容。
- 共享存储:数据统一存放在对象存储或共享存储中(如 Hologres 依托阿里云盘古共享存储,Doris 存算分离模式基于 S3/OSS/HDFS)。
- 本地 Cache 加速:计算节点通过本地缓存热数据,未命中时才从共享存储按需加载,兼顾弹性与性能。
- 计算与存储独立伸缩:查询量大就加计算节点,数据增长就扩存储,互不阻塞,成本按量计费。
需要说明的是,Doris 经历了从"本地多副本"到"存算分离"的演进:Doris 3.x 起提供存算分离部署模式,数据落到对象存储,计算与存储解耦;Hologres 则天生为云而设计,底层即为共享存储架构。两者的差异主要体现在落地形态上,思想殊途同归。
向量化执行与 SIMD
传统数据库(如 MySQL、PostgreSQL)基于 Volcano / 迭代器模型逐行处理数据:每一行都要经过一层层算子(Scan → Filter → Project → Join → Aggregate)的虚函数调用,CPU 开销大、分支预测失败率高、指令流水线利用率低。
向量化执行(Vectorized Execution) 的核心思路是:按列、按批次(Batch)处理数据,每次批量处理 N 行(如 1024 行),一次性对整列数据做运算。它的优势在于:
- 大幅减少算子间的函数调用次数(从"每行一次"降到"每批次一次”)。
- 数据在内存中按列连续存放,内存带宽利用更充分,Cache 命中率更高。
- 批量数据可以直接喂给 CPU 的 SIMD(Single Instruction Multiple Data) 指令,如 SSE / AVX,一条指令同时对多个数据执行相同运算,实现指令级的数据并行。
这里再补充几点:
- SIMD 的适用场景:列式扫描、哈希表构建与探测(Hash Join / Hash Aggregation)、数值表达式求值、谓词过滤、数据编码解码等计算密集型的算子,都是 SIMD 化的重点。
- Doris 的实践:Doris 从 0.15 起引入全链路向量化执行引擎,大量算子(扫描、聚合、Join、表达式)都基于 SIMD 优化;Hologres 同样内置向量化执行引擎,并在共享存储架构下通过向量化 + 行列混合存储保证高性能。
行列混合存储
行存与列存的核心差异在于数据的组织与访问粒度:
- 行式存储:把一整行数据连续存放,适合按主键点查、频繁更新的 OLTP 场景,插入一条记录只需写一个地方。
- 列式存储:把同一列的数据连续存放,适合大规模聚合、范围扫描的 OLAP 场景——查询只读取涉及的列,配合高压缩率,IO 量大幅减少。
在实际系统中,“行存"与"列存"并非非此即彼:
- Doris:默认使用列式存储(Segment 文件按列组织),基于前缀索引(Zone Map / 排序键)与位图索引加速过滤;同时支持表模型(Duplicate / Unique / Aggregate)适配不同业务语义,Unique 模型配合列存也能满足高并发点查。
- Hologres:以列存为主力,同时提供行存表用于高 QPS 点查场景(如在线服务、订单查询),支持行列混合表,让一张表既能做聚合分析又能高效点查,由系统自动路由到合适的存储路径。
Apache Doris 与 Hologres 对比
| 维度 | Apache Doris | Hologres |
|---|---|---|
| 定位 | 开源 MPP 分析型数据库(OLAP) | 阿里云 Serverless 在线分析数仓(OLAP) |
| 架构 | FE(无状态)+ BE(计算存储一体) | 共享计算集群 + 共享存储(云原生) |
| 存算分离 | 3.x 支持存算分离模式(对象存储) | 原生存算分离,计算与存储独立伸缩 |
| 向量化执行 | 全链路向量化,SIMD 深度优化 | 内置向量化执行引擎 |
| 存储格式 | 列式为主,多种表模型 | 列存为主,支持行存与行列混合 |
| 实时写入 | 支持高频实时导入(Stream Load) | 支持实时写入,面向流式数据 |
| 生态 | Apache 开源,社区活跃,Multi-Catalog 联邦查询 | 阿里云生态,与 MaxCompute、Flink 深度集成 |
| 部署形态 | 自建 / 私有化 / 云托管 | 纯云上 Serverless |
实时数仓:MPP 之上的时效性补充
传统的离线数仓以 Hive、Spark 为代表的 T+1 批处理为主,数据从产生到可分析往往滞后一天。而业务对时效性的要求不断提高,催生了"实时数仓”:把数据的采集、加工与分析链条压缩到分钟级甚至秒级,让分析结果尽可能贴近业务发生的当下。
从技术形态上看,实时数仓通常涉及两条路径:
- 流批一体:用一套引擎同时处理流式(实时)与批量(离线)任务,避免两套技术栈的割裂。Flink + Doris、Flink + Hologres 是常见的组合。
- 实时分析引擎:分析侧需要支持高频实时写入与秒级查询,这正是 MPP 分析数据库的强项。Doris 的 Stream Load、Hologres 的流式写入,都为实时数据提供了落库与即时分析能力。
所以,实时数仓并非一种全新的架构,而是在 MPP 并行分析引擎之上补齐了"实时数据接入"这一环。理解了 MPP 的并行执行、列式存储与向量化执行,也就掌握了实时数仓分析侧的核心底座。
为什么 Hologres 能做实时数仓,而 ODPS 不行?
同样是阿里云的大数据产品,ODPS(MaxCompute)查询慢且不能实时,而 Hologres 能做到毫秒级响应,根本原因在于两者设计目标和底层架构的截然不同。
简单来说:ODPS 是为"存"和"粗加工"海量数据而设计的重型武器,而 Hologres 是为"查"和"快用"数据而生的轻骑兵。
🐘 ODPS (MaxCompute):为什么它不擅长实时?
ODPS 的核心目标是高吞吐、低成本地处理海量(PB 级)数据。它面向离线批处理场景,而不是低延迟的在线查询。
- 架构是"慢"的根源:ODPS 基于 MapReduce 或其变种模型。这种模型的特点是分阶段(Map -> Shuffle -> Reduce) 的批量处理。一个查询需要启动多个计算阶段,数据在阶段间流转、落盘,这个过程本身就带来了巨大的开销。同时,它的并行度是静态配置的,需要根据数据量和集群资源提前设定,不够灵活,容易出现资源等待或并行度不足的问题。
- 定位是"批"而非"实":它致力于解决批量结构化数据的存储和计算,适用于 ETL、数据清洗等离线场景,不包含实时数仓所需的索引、主键更新等能力。
- 查询是"异步"的:用户提交一个作业(Job),系统将其加入队列,在资源空闲时才开始计算,整个过程是分钟级甚至小时级的异步操作。
- “慢"的表现形式:
- 资源排队:在共享的计算资源池中,高优先级或先提交的任务会占据资源,你的查询只能等待。
- 数据倾斜:个别节点因分配的数据量过大成为性能瓶颈,拖慢整个查询。
- 模式回退:即便开启了查询加速(MCQA)功能,当查询复杂或数据量大时,系统会自动"回退"到普通的、更慢的批处理模式。
尽管 ODPS 慢,但它依然是数据加工链路中不可或缺的一环,因为它能以极低成本存储和处理海量历史数据。
🚀 Hologres:为什么它能做到实时?
Hologres 是专为实时交互式分析设计的 MPP 架构数据仓库,目标是毫秒级响应。
- MPP 架构:全并行计算:Hologres 采用大规模并行处理(MPP)架构。查询被分解成多个子任务,由集群中所有节点同时、独立地处理自己本地的数据分片,最后汇总结果。这种全并行的计算方式,是其高性能的基石。
- 向量化执行:榨干 CPU 性能:其执行引擎(HQE)大量使用向量化技术。一次处理一批数据而非单行,充分利用 CPU 的 SIMD 指令集,将计算能力发挥到极致。
- 智能存储与索引:Hologres 支持行存、列存、行列共存等多种存储模式,可以为不同查询场景选择最优方案。同时,它利用主键索引等技术,实现了每秒数十万 QPS 的高性能点查。
- 数据即写即查:Hologres 支持高并发的实时写入与更新,数据写入后即可被查询,保证了数据的时效性(写入先落 WAL,再进 MemTable,写入即对读可见)。
- 深度优化与联邦查询:Hologres 通过 SQE 引擎能无缝加速查询 MaxCompute 的数据,无需数据迁移,就能获得 5-10 倍的性能提升。
⚔️ MPP vs. MapReduce:核心差异对比
ODPS(基于 MapReduce)和 Hologres(基于 MPP)代表了两种不同的分布式计算思想,以下是它们的核心区别:
| 特性维度 | MPP (如 Hologres) | MapReduce (如 ODPS) |
|---|---|---|
| 设计目标 | 低延迟的交互式分析(OLAP) | 高吞吐的批量数据处理 |
| 计算模式 | 全并行,所有节点同时计算,实时返回结果 | 分阶段(Map, Shuffle, Reduce),串行执行 |
| 数据交互 | 节点间高效通信,数据流动少 | 大量数据落盘和网络传输(Shuffle 阶段) |
| 查询延迟 | 毫秒/秒级(亚秒级) | 分钟/小时级 |
| 典型场景 | 实时报表、即席查询(Ad Hoc)、在线数据服务 | 海量数据 ETL、数据清洗、离线数仓建设 |
| 资源调度 | 查询级别,按需分配,响应快 | 作业级别,依赖集群调度器,有排队延迟 |
| 适用数据 | 结构化、需要快速响应的热数据 | 结构化、半结构化、非结构化的海量冷数据 |
💎 总结
- ODPS (MapReduce) 的优势在于**“存"和"粗加工”,能以极低成本存储和处理海量数据,但代价是查询慢**。
- Hologres (MPP) 的优势在于**“查"和"快用”,通过 MPP 架构和一系列优化技术实现实时**查询,但成本相对较高。
两者并非替代关系,而是协同工作的理想拍档:ODPS 负责低成本地存储和加工海量数据,而 Hologres 则负责对加工后的数据进行极速、实时的查询与服务。
深入原理:Hologres 的 HSAP 架构、查询引擎与存储引擎
前面从"设计目标"层面解释了 Hologres 为什么能实时。这一节再往下挖一层,结合 Hologres 官方技术揭秘(查询引擎、存储引擎、核心架构三篇文章),看看它在架构、执行引擎和存储引擎三个层面分别是怎么设计出来的。
HSAP:为什么"一套系统"能同时做服务和分析?
Hologres 的定位是 HSAP(Hybrid Serving & Analytical Processing,服务分析一体化):同一份数据、同一套系统,既要支撑高 QPS 的在线查询(Serving,如点查、接口服务),又要支撑复杂的离线分析(Analytical,如多维聚合、BI 报表)。
为什么需要这种设计?传统方案各有痛点:
- 传统离线数仓:ETL 链路长、只能处理 T+1 数据,无法支撑实时场景。
- Lambda 架构:在离线数仓之上再加一套实时链路,然后在服务层做 Merge。两套引擎、多份数据存储,带来数据一致性问题和高维护成本。
Lambda 架构:实时数仓出现前的"标准答案”
在 HSAP 出现之前,业界对"既要实时、又要全量准确"的标准解法是 Lambda 架构:把一条数据链路拆成两条,各取所长。
Lambda 架构由三层组成:
- 批处理层(Batch Layer):负责全量历史数据,定期跑批任务(如 Hive / MapReduce)重算全量结果,产出准确但延迟高的 Batch View(分钟到小时级)。
- 速度层(Speed Layer):负责增量实时数据,用流式计算引擎(如 Storm / Flink)对新到数据做增量聚合,产出低延迟但不完整的 Realtime View(秒级)。
- 服务层(Serving Layer):把 Batch View 和 Realtime View 合并后对外提供统一查询——既能看到历史全量,又能看到最新增量。
听起来很合理,但落地时问题不少:
- 逻辑写两遍:批处理和流处理各实现一遍业务逻辑,两套代码维护成本高,还容易不一致。
- 数据对不上账:批视图按全量重算、实时视图按增量累计,两份结果口径不同,Merge 时经常出现重复、乱序、对不齐。
- 多套系统、多份存储:批链路、流链路、合并服务各是一套系统,运维和排障都很痛苦。
HSAP 的核心思想是统一数据存储 + 统一查询服务:实时数据和离线数据落进同一份存储,服务和分析走同一个 SQL 接口,避免数据搬运与多份拷贝。
这套架构的关键是存储计算分离:数据全部存放在分布式文件系统(盘古 / HDFS)中,Backend 计算节点无状态、可弹性扩缩容。计算负载上来就加计算节点,数据增长就扩存储,互不阻塞。底层还提炼了 HOS(HoloOS) 异步无锁框架,保证高并发下 CPU 多核的高利用率。
查询引擎:异步 DAG + 分布式执行计划
Hologres 的执行引擎是完全自研的,而不是在开源引擎上做改造。为什么?文章给出的理由是:传统 MPP 引擎支持通用 SQL 但对实时场景优化不足;Druid、ClickHouse 这类专为实时场景设计的引擎,单表查询快但复杂查询(多表 Join)性能差。Hologres 的目标是两者兼得。
它的核心设计有四点:
- DAG 执行图 + 异步算子:执行计划由一组异步算子组成的 DAG(有向无环图)表示,可以表达任意复杂查询,也方便对接优化器做各种优化。
- 分布式执行与 Exchange:表按 Distribution Key(分布键)散列到多个 Shard(分片),执行计划按数据位置切分为多个 Fragment(片段)下发到对应节点并行执行,片段之间通过 Exchange 算子交换数据。如果 Join 键恰好与分布键一致,还能避免跨节点传输数据。
- 全异步执行:整个后端(执行引擎 + 存储引擎)统一使用 HOS 提供的异步无锁框架。每个 Fragment 实例对应一个逻辑调度单元(EC),算子和存储引擎全部异步执行。这在存储计算分离架构下尤其重要——异步的"多发几个 GetNext"机制,可以把并发读请求发出去,读完成时自然触发下游处理,规避了远程读数据的延迟,同时把 CPU 打满。
- 向量化 + 延迟计算:内存中按列存储,算子内部尽量向量化执行;扫描时支持延迟物化——先过滤,再按需读取需要的列,过滤后整批不满足条件的列根本不读。
一句话总结查询引擎的思路:分布式执行计划切分到数据所在节点,全异步流水线把每个 CPU 核都喂满,向量化把单核吞吐榨干。这也呼应了前面"为什么能并行计算"一节:并行不是执行时临时拼出来的,而是从数据分片、算子设计到调度模型,整套都是为并行而生的。
存储引擎:LSM 写入路径与多版本读
Hologres 的存储引擎采用 LSM(Log-Structured Merge) 技术,写入路径是典型的"先写日志,再写内存表,最后刷盘合并":
这一设计带来了三个关键能力:
- 写入快且不丢数据:写入先落到 WAL(预写日志),再写 MemTable;WAL 持久化后数据才算成功,即使节点宕机也能从日志恢复。相比传统 B+ 树的随机写,LSM 的全 append-only 顺序写大幅降低了随机 IO。
- 写入即读:MemTable 写完后对新读请求直接可见(read-your-writes),数据时效性到秒级甚至亚秒级。这也是"实时数仓"里"实时"二字能落地的根本保证。
- 读写互不阻塞:存储引擎采用 snapshot read(快照读),读请求带一个读取时间戳构造 Snapshot LSN,大于该 LSN 的新写入会被过滤。写是 append-only,读是快照,两边都不需要加锁,天然支持高并发混合负载。
存储上还支持行存 / 列存两种格式:行存适合主键点查(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。
缺点与代价
- 成本高,内存密集型:MPP 分析库把数据尽可能压在内存和 SSD 中换取速度,节点规格高、按量计费贵。它是热数据引擎,不是廉价存储——把全量历史数据塞进去成本会爆炸。生产实践中通常是"ODPS 存全量、Hologres 存热数据"的分层组合。
- 分布式 Join 是软肋:大表 join 大表需要 shuffle,数据在节点间网络搬移,网络带宽就是瓶颈;当 join 中间结果超出内存后,性能会急剧下降。
- 数据倾斜敏感:热点 key 集中在某一个节点,导致单点打满、拖垮整个查询。这与 ODPS 的倾斜问题同源,只是并行架构把问题推迟出现而已。
- 更新与删除代价高:LSM 顺序写确实快,但列存文件上的 UPDATE/DELETE 需要标记删除加后台合并,高频小粒度的行级更新不是它的主场。
- 混跑资源隔离难:Serving(在线点查)与 Analytical(大查询)同池运行,一个重查询可能抢占资源、拉低在线 QPS,需要精细的资源组与队列配置,运维门槛不低。
- 闭源与厂商锁定:Hologres 是阿里云商业产品,语法与工具链绑定其生态,无法自建或迁移;对比之下,Doris、ClickHouse 开源可控、社区活跃。
- 复杂 SQL 能力有上限:单表与宽表查询性能极佳,但在极高基数、超复杂多表关联、自定义 UDF 生态等方面,不如 Presto、Spark 这类通用引擎灵活。
不适合的场景
| 场景 | 为什么不适合 | 更合适的选择 |
|---|---|---|
| 海量冷数据长期存储 | 存储成本爆炸 | OSS / ODPS |
| 超大表全量 Join 计算 | shuffle 瓶颈 + 数据倾斜 | Spark / Presto |
| 高频小粒度事务写入 | 更新与删除代价高 | MySQL / PolarDB |
| 超高并发在线 KV 点查 | 杀鸡用牛刀,成本高 | Redis / Tair |
| 全文检索 / 非结构化数据 | 结构化分析型引擎 | Elasticsearch |
| 需要自主可控、免厂商锁定 | 闭源绑定云生态 | Doris / ClickHouse |
选型建议
Hologres 把所有资源押在"热数据 + 高并发分析"这一件事上,所以它快;代价是贵、吃内存、Join 与倾斜敏感、闭源锁定。适合它的典型场景是:实时报表、即席分析、在线数据服务,且数据量在可承受的成本范围内。而数据仓库的完整链路(海量存储、复杂 ETL、深度数据挖掘)仍然需要 ODPS、Spark 等引擎配合——各司其职,才是合理的架构。
小结
MPP 架构的底层逻辑其实很朴素:数据拆开、任务拆开、并行执行、结果合并。而现代 MPP 分析数据库之所以能把性能做到极致,靠的是几个关键技术的叠加:
- Shared-Nothing 的 MPP 架构解决"怎么并行"的问题;
- 列式存储解决"怎么少读数据"的问题;
- 向量化执行 + SIMD解决"怎么算得快"的问题;
- 存算分离解决"怎么弹性与省钱"的问题。
理解了这条主线,再去看 Doris、Hologres、ClickHouse 等任何一款分析引擎,都能很快抓住其设计精髓。
参考链接
- Hologres 技术揭秘-查询引擎篇: https://developer.aliyun.com/article/784506
- Hologres 技术揭秘-核心架构篇: https://developer.aliyun.com/article/779118
- Hologres 技术揭秘-存储引擎篇: https://developer.aliyun.com/article/779284