1. MPP到底是什么?先从一个查询说起
先明确一点:MPP(Massively Parallel Processing)是“大规模并行处理”的意思。它不是某一个具体的数据库软件,而是一类架构思想——把一个大任务拆成很多小任务,交给一堆独立的处理单元同时干,最后把结果汇总起来。我们常说的Greenplum、Teradata、Vertica、ClickHouse分布式集群、Apache Doris,本质上都是MPP架构或MPP风格的产物。
想理解“MPP是什么”,最好的办法不是背定义,而是看一条SQL语句在一台机器上和在一群机器上是怎么跑的。
假设你有张订单表,10亿行,跑一个简单的分组统计:SELECT region, SUM(amount) FROM orders GROUP BY region;。单机数据库的处理方式是:一个进程把10亿行全扫一遍,扫完自己算。听起来没什么问题,但当表到几百GB、几个TB甚至更大时,单机瓶颈就来了——要么内存装不下,要么CPU算不动,更不用说索引膨胀、备份耗时的连锁反应。MPP的思路则是:10亿行数据按某种规则切开,分散存储在100台机器上,每台机器只扫自己那1000万行,各算各的SUM,然后把100个局部结果汇总成最终结果。理论上,处理速度接近单机的100倍。这就是“大规模并行”最朴素的含义。
一句话概括:MPP是一种通过“多机分工+数据分片+结果汇总”来突破单机性能极限的数据库架构。它解决的核心问题是——数据量超过单机处理能力之后,我们怎么用一堆普通服务器组成一台“逻辑上的超级数据库”。适合谁关注?第一类是数据仓库选型的工程师,第二类是做大数据的研发,第三类是准备系统架构相关面试的人。这个系列后面几篇我会分别展开执行引擎、存储模型、调优手段和集群运维,这篇先打好基础。
注意:MPP并不等于“分布式数据库”的全部。后面章节我会专门对照解析,先把概念边界搞清楚,后面才不容易被各种营销词带偏。
2. 深入MPP核心架构
2.1 什么是Shared Nothing架构
MPP最典型的架构标签是Shared Nothing,翻译过来叫“无共享架构”。这个名字听起来玄乎,其实就是说:集群里的每一台机器都有自己独立的CPU、内存和磁盘,没有任何硬件资源是互相共享的——不共享内存,不共享磁盘,彼此之间只通过网络连接通信。
对比一下就明白了。传统大型机常采用Shared Everything架构,多颗CPU共享同一块内存和同一批磁盘。好处是编程简单,CPU之间通信走内存带宽,快得不行;坏处是扩展受限于总线带宽和内存容量,而且整机价格贵得离谱。还有一类是Shared Storage架构,很多机器共享一套存储设备,Oracle RAC就是典型。这种架构存储好扩展,但有个致命问题——多台机器同时读写同一份数据,必须靠分布式锁来协调,锁竞争一上来,性能就很尴尬。
MPP选Shared Nothing是深思熟虑的结果。既然每台机器数据完全独立,那么查询时各算各的,几乎不存在跨节点资源争用。扩展性也直白:一台机器不够,再加一台,数据分片重新分布一下就行。整个集群能力和节点数近乎线性增长——这是MPP能撑起几十TB甚至PB级数据仓库的根本原因。
2.2 三类节点的角色分工
几乎所有的MPP数据库都有三个逻辑角色,虽然各家叫法不同,但干的活大同小异。
第一类是协调节点(Coordinator Node),Greenplum里叫Master,Teradata里叫主节点。它不存业务数据,专门负责接收SQL、生成执行计划、把任务拆解分发给下面的计算节点,然后收集结果、组装返回给客户端。它像是一个项目经理,自己不搬砖,但统筹全局。
第二类是计算节点(Segment Node / Compute Node / Worker Node),真正干活的。它们各自持有数据分片,执行协调节点下发的子任务,把局部结果返回给协调节点。在分析型查询里,计算节点之间也会互相通信——比如做Join时,两边数据不在同一个节点上,就必须把数据发给对方。这种节点间数据交换叫Shuffle,是MPP查询中最耗时、最容易出问题的环节。
第三类是存储层。严格说它不是“节点”,但在MPP里,数据在磁盘上的分布方式直接决定了计算效率。有些MPP用本地盘(每块数据只存在某一台机器上),有些用共享对象存储,各有利弊,后面细讲。
做个类比。你开了一家连锁餐厅,总部(协调节点)只负责接单、分解任务,各分店(计算节点)在自己厨房里炒菜。如果某道菜的食材在A店、调味料在B店,A店就得向B店要货——这就是跨节点通信。菜炒好后各店交回总部,总部统一打包给顾客。这个模型最怕什么?最怕某家分店是个爆款菜,所有订单都挤到它那儿,其他分店闲着——这在MPP里叫数据倾斜,后面我会用专节讲。
2.3 数据分布策略:为什么Hash分片是主流
协调节点拆任务容易,真正难的是数据怎么分。分不好,某些节点忙死、某些节点闲死,整个集群白搭。MPP常用三种分布策略:Hash分布、随机分布、复制表。
- Hash分布(Hash Distribution):对某个字段(一般是Join关联字段或GROUP BY字段)做哈希,相同哈希值的行固定到同一台机器。好处是查询时如果按这个字段Join或Group,数据已经在本机了,不需要跨节点搬数据,这是最理想的情况。
- 随机分布(Random Distribution):数据轮询或随机放到各节点。写起来快,但如果查询要按某字段聚合,就得全量Shuffle一次。
- 复制表(Replicated Table):小维表在每个节点各放一份。比如地区维表、分类维表,几百行数据复制到所有节点,Join时大家用本机副本就行,彻底消灭跨节点传输。
为什么Hash分布是绝对主流?因为它能把“未来可能的Join需求”提前在数据分布阶段就处理好。比如订单表和用户表都按user_id做Hash,查询orders JOIN users ON orders.user_id = users.id时,每个节点本地就有订单和它对应用户的全部数据,无需任何数据搬运,直接本地算完。这就是MPP性能出色的核心原因之一——能提前规避的通信,绝不留到查询时解决。
2.4 从SQL到底层执行计划的全过程
MPP里一条SQL的旅程,比单机数据库多好几个环节。我以Greenplum为例,梳理一遍:
第一步,客户端把SQL发给Master节点。第二步,Master做解析和优化:生成执行计划,但这不是单机计划,而是一个分布式执行计划——每个步骤都标注了“这段逻辑在哪个节点跑、跑完结果要不要广播出去”。第三步,Master把计划切分成一个个任务片段,分发到所有Segment。第四步,各Segment并行执行自己的片段,比如扫描本地数据、做局部聚合、做局部Join。第五步,如果查询涉及跨节点数据,Segment之间用Interconnect(节点间高速互联通道)直接交换数据。第六步,各Segment把局部结果返回给Master,Master做最后的汇总排序,返回给客户端。
这里面有个关键点:不是所有数据都要回Master。如果只是求SUM,每个Segment把局部SUM发给Master,Master把几个数加起来就行,传输量极小。但如果ORDER BY全局排序,数据就必须汇聚到Master统一排——这种操作在高并发场景下会成为瓶颈,也是后面要讨论的“MPP不适合跑高频点查”的原因之一。
2.5 计算下推:MPP快的真正秘密
很多人以为MPP快是因为机器多,这没错,但只说对了一半。更深的秘密是“计算下推”(Predicate Pushdown)——把计算逻辑推到离数据最近的地方执行,而不是把数据拉上来再算。
在传统单机架构里,数据在磁盘上,计算在内存里,要先读进内存才能算。在MPP里,每台Segment机器本地就是数据的“owner”,过滤、聚合、投影、Join这些高消耗操作全部在本地完成,只有中间结果通过网络传输。数据不动,计算动,这句口号就是MPP的精髓。
举个实际感受过的例子。我在一个数百GB的日志表上跑月维度聚合查询,如果数据没有按时间Hash,查询就得把所有数据网络传输一遍,耗时接近分钟级;按日期字段重新设计分布键之后,每个节点只管自己那段时间的数据,查询直接降到秒级。同样的SQL,差别可以到几十倍。所以很多MPP调优的第一课,就是“设计分布键就是设计性能”。
3. MPP平台支持全景:主流产品与生态
3.1 商业MPP数据库:老牌玩家的积累
MPP最早的成功商业化是Teradata。在数据仓库领域,Teradata是教科书级别存在,从上世纪80年代开始就在做大规模并行处理,其独创的BYNET互联层和优化器,至今仍是很多分布式数据库参考的对象。但Teradata是软硬一体设备,价格极高,主要服务金融、电信、零售这些大行业。
Vertica是另一类代表。它的特点是列式存储+MPP,压缩比极其出色,查询速度快。2011年被HP收购后,又在云原生演进上花了很大力气,现在主打分析型云数据仓库。这些商业产品技术成熟、功能完善,但License成本高、人才门槛也高,一般中小团队驾驭起来比较吃力。
实操心得:我不建议小团队一上来就选商业MPP。如果你只是在验证MPP方案,开源的Greenplum、Doris可能更适合起步,跑通后再评估要不要为稳定性付费。
3.2 开源MPP生态:活跃但各有取舍
开源阵营是很多人实际接触MPP的起点。
Greenplum:PostgreSQL生态的MPP代表,每台Segment就是一个独立的PostgreSQL实例,支持标准SQL、窗口函数、复杂Join。功能全面,但比较“重”,节点管理、参数调优复杂度高,对运维能力有一定要求。
Apache Doris:由百度开源的分析型数据库。它的MPP架构做了很多工程上的取舍,比如不依赖外部组件就能部署,支持Rollup表、物化视图,在报表类查询上性能非常亮眼。近年社区活跃度和使用面都增长很快,是很多互联网公司做OLAP报表的主力选择。
ClickHouse:用“MPP风格架构”描述更准确。它的核心是列式存储+向量化执行,做了极致的单机性能优化,多节点部署时数据分片也支持分布式查询。但它的MPP特性不如Greenplum那么“正统”,比如分布式Join需要手动处理,支持度有限。它最大的优势在于单表扫描和聚合极其快,非常适合明细查询、日志分析、时序场景。
StarRocks:从Doris社区分叉出来的。主打极速分析,全面向量化执行引擎,在Doris的基础上强化了Join性能、物化视图和实时导入能力,社区关注度很高。我做选型对比时,StarRocks在高并发聚合查询和小表Join场景上确实有明显优势。
做一个简表直观对比:
| 数据库 | 核心定位 | 存储模型 | 适用场景 | 主要短板 |
|---|---|---|---|---|
| Greenplum | 大规模MPP数仓 | 行存+列存混合 | 复杂查询、超大规模数仓 | 运维重、并发有限 |
| Doris | 交互式OLAP | 列存为主 | 报表查询、多维分析 | 复杂SQL能力稍弱 |
| StarRocks | 极速分析 | 列存+向量化 | 高并发点查、实时分析 | 生态没有Greenplum丰富 |
| ClickHouse | 单表分析 | 列存 | 日志、时序、明细看板 | 分布式Join支持弱 |
3.3 云厂商的MPP服务:零运维时代
云上平台是近几年的绝对主流。几乎所有公有云厂商都把MPP能力做成了托管服务,用户不用装机器、不用管集群,开个实例就能用。
AWS Redshift是最典型的代表。它的架构源自PostgreSQL,但做了彻底的MPP改造,存储分离的架构让它在扩缩容上非常灵活。Snowflake则走得更远,把存储、计算、服务三层彻底解耦,计算集群可以独立伸缩,做到了“一个集群算数,另一个集群做报表”,互不干扰。国内云厂商方面,阿里云的AnalyticDB、华为云的GaussDB(DWS)、腾讯云的TDSQL也都在PaaS层提供了MPP能力,适合不想自建集群的团队。
云上MPP最大的优势是弹性——业务忙时扩节点,闲时缩容,按量付费。缺点是OpenAPI生态通常不如原生开源产品丰富,深度定制空间有限。
3.4 硬件与部署形态:从物理机到容器化
平台支持里有个容易被忽略的问题是“跑在哪”。早期MPP基本绑定物理机,每个节点一台服务器,磁盘直接挂在本地,性能稳定但扩展流程重。后来虚拟化普及后,MPP也能跑在VM上,但要注意I/O性能的损耗。
现在更常见的是容器化部署。MPP数据库对网络和I/O要求极高,容器虽然带来了部署便利,但也引入了网络叠加和存储驱动的额外开销。我实际用Kubernetes部署过Greenplum,体验是:可行,但需要仔细调优网络插件,否则跨节点性能损耗明显。
还有一类要提的是“存储计算分离”的新形态。传统MPP是存储和计算绑定在一台机器上——数据在本地盘上,只能被本机计算。但Snowflake、Redshift的新版本、GaussDB(DWS)都支持把数据放到底层对象存储,计算节点无状态化,需要时随时拉起。好处是扩缩容极快、成本低,但查询延迟会变高一些。在“性能极致”和“运维轻量”之间,新一代MPP平台越来越多地倾向后者。
3.5 平台选型的底层思考
我做了多年数据平台选型之后,最深的感受是:不能只看“能跑多快”,还要看“是否养得起”。
MPP平台选型至少要想清楚四个维度:性能、成本、运维、生态。前两者好理解,运维往往被低估——没有专职DBA的团队,慎重选Greenplum这类重型方案;生态则决定了你遇到问题是自己趟坑,还是搜索引擎能找到一堆答案。商业产品功能全但贵,开源产品活跃但杂,云原生服务省心但被绑定。没有包治百病的方案,只有适合你团队现状的取舍。
注意:MPP平台通常以“集群”形态运行。如果单机就能搞定的数据量(比如几个GB到几十GB),完全没有必要上MPP,投资回报率极低。后面第5部分我会专门说这个边界。
4. MPP适合做什么、不适合做什么
4.1 主战场:复杂的分析型查询
MPP的主场是数据仓库场景下的复杂分析:多表关联、大范围聚合、窗口函数、多级子查询。这类查询通常扫描数据量大、计算复杂、单条SQL跑得久,但对延迟不那么敏感,对并发量要求也不高。
典型的例子:电商平台月末统计全站销售额按品类、地区、时间维度的多维报表;金融系统做客户行为分析,几千张维表关联出上亿用户的画像特征。这类查询单机数据库跑到卡死,MPP用并行能力轻松扛住,这就是它最舒服的“射程”。
4.2 绝对禁区:高并发的点查和写入
MPP有个明显的“软肋”:不适合高并发小查询。你想一下,如果每秒来一万个SELECT * FROM user WHERE id = ?,这些查询每个都要经过协调节点、生成执行计划、发给Segment、汇总返回,走完一整套分布式流程。而一个单机数据库可能几条毫秒就返回了。MPP在这种场景下不是“快”,而是“浪费”——为了一条小查询动了整个集群的计算资源。
写入也一样,尤其是高频单条INSERT,每一条都要经过分布式协调,性能惨不忍睹。联机交易(OLTP)场景交给专门的OLTP数据库,MPP不是干这个的料。选中型数据量的“轻度分析”,用普通单机数据库加索引、加缓存往往更合适。
4.3 与Hadoop/Spark、HTAP的关系辨析
很多人问:MPP和Hadoop/Spark有什么区别?本质区别在于MPP是“数据库”,有完整的SQL语义、事务(不同程度的)、优化器和数据类型,最关键的是它的执行引擎是为低延迟交互式分析设计的;而Hadoop/Spark是“计算框架”,专注批处理,不提供数据库层面的SQL完整实现,你需要自己组织任务、管理状态。简单说,MPP是“开即用的数据库”,Spark是“要组装的工具箱”。
HTAP(Hybrid Transactional/Analytical Processing)是另一类新概念,指一套系统同时兼顾交易事务和分析负载。有些产品号称HTAP,但实际上在OLTP和OLAP两端都达不到专业水平。工程上常见做法是“OLTP库+MPP数仓+ETL同步”,各自用各自最擅长的架构,别听一句话就冲动迁移。
5. 进入MPP世界,先弄清楚这几个概念
5.1 列存、向量化与MPP的关系
很多人把“列存”和“MPP”混为一谈。MPP说的是“并行执行”,列存说的是“数据存储格式”,两者只是经常搭配出现,并无必然因果。MPP数据库也可以行存,只是分析型场景下列存优势太大,所以高度并行+列式存储的组合成了主流。
列存的好处是极致的压缩和IO优化:查询只要读需要的列,而不用触碰无关列。而向量化执行则是把“一次处理一行”改成“一次处理一批”,充分利用CPU的SIMD指令集。列存减少数据读取量、向量化提升数据计算效率,再加上MPP的多机并行,三个技术叠在一起,就是现代分析型数据库性能神话的来源。
5.2 数据倾斜和网络瓶颈
MPP集群的性能上限,不取决于最快的节点,而取决于最慢的节点。数据倾斜就是症结本源——Hash分布的字段值分布不均,某个值的数据量特别大,比如全国人口表按“省份”Hash,河南省比其他省份多几倍,那对应节点就会比其他节点慢好几倍,整个查询就这样被拖住。
另一个隐藏瓶颈是网络。MPP节点间通信走以太网,数据Shuffle量一大,网络带宽就成了天花板。这也是为什么MPP集群对网络质量要求极高,万兆网络是起步要求。如果用了普通千兆,跑大型Join时一看监控,网络先满载了。
5.3 新人最常遇到的几个概念陷阱
第一个陷阱是“MPP等于性能无限”。实际上,MPP性能受最弱节点和网络带宽制约,盲目加节点有时反而因为数据分布开销导致性能下降。第二个陷阱是“MPP可以完全代替单机数据库”。维度表或小表完全没必要大动干戈上MPP,复杂度和成本长期看都得不偿失。第三个陷阱是“MPP适合所有分析场景”。低延迟小查询、高频点查,MPP反而可能是最差的选择。第四个陷阱是“MPP一定比Hadoop快”。这取决于任务模型。GB级别数据,MPP快;PB级别全量ETL,Hadoop的批处理吞吐能力其实更强。没有万能架构,只有场景匹配度。
这些概念看清楚之后,下一篇我再展开MPP执行引擎的细节——从并行Join算法、Shuffle策略到资源队列的分配方式,把这些“高级能力”讲透。大家对MPP有哪些具体困惑,可以直接在评论区提,选型或调优问题我会尽可能给结论。