MPP数据库分片与数据倾斜实战指南:从原理到选型

举报
数据库小学妹 发表于 2026/10/21 16:34:13 2026/10/21
【摘要】 把 MPP 数据库从原理讲到落地:一条查询怎么拆开并行跑,分布键怎么选,倾斜怎么定位和止血,改键怎么迁移,哪些场景不该上,POC 该测什么。附排查 SQL、前后对比和检查清单。

大家好,我是数据库小学妹👋我踩过的坑,你别再踩。

去年一次架构评审,团队要把单机报表库换成 MPP 数据库。理由很直接,多加几台机器就快了。三个月后,同一个团队凌晨给我打电话。8 个节点,7 个在 20% 上下,1 个跑到 92%。一条汇总 SQL,从 30 秒变成 2 分 06 秒。评审会上的乐观和凌晨的报警,说的是同一件事。机器不是白加的,得先知道查询是怎么跑完的。

这篇把三件事串起来。MPP 数据库在并行什么,数据倾斜怎么找出来,什么场景不该上。看完能少走一段弯路。

MPP 数据库是什么?分片、并行与三类角色

MPP 数据库,底层是 Massively Parallel Processing(大规模并行处理)。落地就三个动作。数据按分布键切到多个节点。查询拆成并行任务。各节点算完,再汇总结果。

它擅长大表扫描、复杂 join、聚合分析。高并发短事务不是它的强项。把它当成单机数据库的加速版,会误判适用边界。它是为分析型负载设计的并行架构。

分布式数据库和 MPP 也不是一回事。前者说的是部署形态,后者说的是计算架构。一个分布式数据库可以是 MPP,也可以不是。MPP 系统通常分布在多节点上。它的强项是分析,不是跨节点事务。

换成角色看更清楚。协调节点负责解析 SQL、生成计划、拆任务、收结果。计算节点只扫自己那份数据,算本地聚合。分片决定每一行落在哪个节点。

角色 主要做什么 出问题时的表现
协调节点 解析 SQL、生成计划、拆任务、汇总 并发高时先忙不过来
计算节点 扫描本地分片、执行 join 和聚合 某个节点 CPU 或 IO 冒尖
数据分片 决定每一行落在哪个节点 分布键选错,负载一边倒

MPP 的核心不是节点多。是每个节点只干自己那份活。数据分得匀,并行才有意义。分得不匀,节点再多也是一个人干活,其他人等。

这里有个容易混的点。并行是一条查询拆开跑,并发是多条查询一起跑。MPP 强在并行,不代表能扛高并发。协调节点要一直接任务、拆计划、收结果。并发一高,它先成瓶颈。

MPP 数据库执行计划:一条 SQL 怎么并行跑完

一条查询在 MPP 数据库里通常五步。解析、优化、拆计划、并行执行、汇总。前两步在协调节点完成。扫描、join、聚合下沉到计算节点。

难点在“数据怎么到该去的节点”。join 常见三种走法。

join 策略 怎么做 适合什么情况
本地 join 两表按同一个键分布,数据已在同一节点 大表 join 大表,分布键就是 join 键
广播 join 把小表复制到每个节点 一张表很小,另一张很大
重分布 join 两表都按 join 键重新洗一遍 两张表都大,分布键对不上

本地 join 最省,前提是分布键和 join 键一致。这一点要在建表时想好。表建完再改,代价是搬数据。广播适合小表。小表一大,网络和内存都吃不消。

执行计划里,重分布长这样:

Gather
  -> HashAggregate
       -> Redistribute (city_id)
            -> Seq Scan on fact_order

Redistribute 把各节点的部分结果按分组键重洗一遍。Broadcast 把小表复制到每个节点。两个动作都走网络。网络一堵,最慢节点决定整个 stage 的时长。优化器最怕两件事。统计信息不准,它估错行数。分布键选错,它算错数据在哪。

看执行计划有个简单顺序。先找 Scan,数据量大说明过滤没下推。再找 Redistribute,流量大说明分布键和 join 键对不上。最后看 Gather,它等谁,谁就是最慢节点。

金仓 KADB 走的是同一套执行模型。协调拆任务,计算节点算本地分片,重分布和广播都走网络。看执行计划判断瓶颈,方法通用。具体视图名以版本手册为准。

MPP 数据库分布键怎么选:四种分片方式与三条标准

分片方式常见四种。Hash 最常用,按 hash 值取模落节点。Range 按区间切,适合按时间增长的数据。List 按枚举分,适合地区、租户类型。复制分布每个节点存一份,只适合小维表。

Hash 匀不匀,看三件事。基数够不够高,数据匀不匀,是不是高频 join 键。三条都满足,再考虑复合键。复合键能提高均匀度。但 join 只用其中一列时,数据不一定还在同一个节点。

候选列 适合吗 风险
订单号这类高基数主键 适合 和 join 键不一致时仍要重分布
客户号、商户号 看情况 大客户会吸到一个节点
城市、地区、日期 谨慎 热点值造成明显倾斜
状态位、类型码 不适合 基数低,业务一偏就挤

分布键和分区键不是一回事。分布键决定数据去哪个节点,分区键决定数据在节点内怎么切。一个管节点之间,一个管节点之内。两个都要看,别只改一个。

选键之前,先跑数:

SELECT city_id, count(*) AS cnt
FROM fact_order
GROUP BY city_id
ORDER BY cnt DESC
LIMIT 10;

WITH dist AS (
  SELECT city_id, count(*) AS cnt
  FROM fact_order
  GROUP BY city_id
)
SELECT
  round(max(cnt)::numeric / avg(cnt), 2) AS skew_ratio,
  round(max(cnt)::numeric / sum(cnt), 4) AS max_share
FROM dist;

演示表 120 万行,8 个节点。最大的城市占 62%,skew_ratio 是 18.6。8 节点的理想最大占比是 12.5%,62% 是它的五倍。看到这种数字,先查分布键,别急着改 SQL。这套判断不绑定产品,金仓 KADB 也按分布键把数据切到各节点。换的只是建表语法和系统视图名。

MPP 数据库数据倾斜怎么排查:四个原因与止血办法

数据倾斜,就是一部分数据集中在一个节点,其余节点在等。症状很典型。一个节点 CPU 或 IO 冒尖,stage 时长等于最慢节点。落盘次数变多,网络流量集中。

数据倾斜的四个原因

原因就四个。分布键基数低,热点值太大,空值太多,join 键和分布键对不上。空值和基数可以单独确认:

SELECT
  count(*) FILTER (WHERE customer_id IS NULL) AS null_rows,
  count(DISTINCT customer_id) AS customer_ndv
FROM sales_detail;

应急止血:加盐、条件下推与预聚合

加盐能打散热点。先按客户加随机盐做局部聚合,再去盐收口。行数少、热点不明显时,加盐反而多一层开销。

WITH partial AS (
  SELECT
    customer_id,
    floor(random() * 16)::int AS salt,
    sum(amount) AS amount
  FROM sales_detail
  GROUP BY customer_id, salt
)
SELECT customer_id, sum(amount)
FROM partial
GROUP BY customer_id;

暂时不能改表,先做三件事。过滤条件下推,把中间结果压小。小表广播,避免大表重分布。先局部聚合,再全局聚合,减少重分布的数据量。三招都是止血,不是治本。

四个原因不挑产品。金仓 KADB 上的处理顺序也一样。先定位热点值,再决定换键、预聚合还是加盐。换产品,换的是命令,不是思路。

周巡检 SQL 与阈值

长期稳定靠巡检。这条 SQL 我放进周任务,只看最近 7 天。

WITH dist AS (
  SELECT city_id, count(*) AS cnt
  FROM fact_order
  WHERE order_date >= CURRENT_DATE - 7
  GROUP BY city_id
)
SELECT
  round(max(cnt)::numeric / avg(cnt), 2) AS skew_ratio,
  round(max(cnt)::numeric / sum(cnt), 4) AS max_share
FROM dist;

阈值这么定。skew_ratio 小于 1.5、max_share 小于 15%,算正常。超过 3,或者 max_share 超过 25%,排期处理。节点越多,理想占比越低,阈值跟着调。

数据倾斜怎么治:改分布键的迁移与前后对比

数据倾斜治本的办法,多数时候是换一个更均匀的分布键。代价是搬数据。低峰期用 CTAS 建新表,灌完对账,再切视图或改表名。

CREATE TABLE fact_order_new (
  LIKE fact_order INCLUDING ALL
) DISTRIBUTED BY (order_id);

INSERT INTO fact_order_new
SELECT * FROM fact_order;

ANALYZE fact_order_new;

改键前后对比

同一套演示数据,改前改后差得很明显。

指标 改前(city_id) 改后(order_id)
总耗时 126 秒 34 秒
最慢节点耗时 118 秒 31 秒
最大节点占比 62.0% 13.1%
落盘次数 3 次 0 次

迁移步骤与依赖检查

切之前把依赖查清楚。视图、物化视图、索引、外键、同步任务,一个都别漏。我漏过一个物化视图,重分布后报表空了一天,被业务追着问。

迁移顺序我一般这么走。选低峰窗口,确认同步链路能停多久。建新表,显式指定分布键。灌完对账行数和金额。跑三条典型 SQL,对比最慢节点。查完依赖,切表或切视图。观察一周,保留回滚表。步骤不复杂,难的是每一步都别省。

金仓 KADB 这类国产 MPP,迁移和运维还有一层本地化支持。改分布键、扩容、故障处理,遇到问题能找到人一起看。技术上能不能做是一回事,出问题时有没有人兜底,是另一回事。具体范围以厂商承诺为准。

MPP 数据库适合什么场景:四类负载别硬上

MPP 数据库适合大表、少并发、复杂分析。不适合的也很明确。几千 QPS 的点查,每条都要协调、拆任务、汇总,调度成本比计算还高。频繁更新和跨节点事务,代价都不低。数据量只有几十 GB,单机加索引就能扛。团队没有分布式运维经验,监控体系也没建起来,别急着上。

维度 MPP 数据库 分布式 OLTP 数据库 单机数据库
主要负载 大表扫描、复杂 join、聚合 高并发短事务、点查 中小规模事务和分析
事务能力 跨节点事务代价高 强事务是核心 单机事务成熟
扩展方式 加节点、重分布数据 分片和副本 垂直扩展为主
典型场景 数仓、BI、报表、离线分析 订单、支付、账务 中小业务、开发测试

架构选型的第一原则,是匹配负载,不是追新。选之前先问自己。你的查询是等结果的交互分析,还是跑几小时的长任务。答案不一样,路线就不一样。

高并发小查询这条最容易误判。每条查询都要协调、拆任务、汇总。几千 QPS 压上去,先扛不住的是协调节点。不是 MPP 做不到,是它做这件事不划算。

MPP 数据库会被湖仓替代吗?

我的判断是,边界在融合,不是简单替代。MPP 在补联邦查询和向量化,湖仓在补 SQL 和并发。选哪个,还是看查询形态和团队。

MPP 数据库怎么选型:POC 要测的七件事

选型别只看厂商的 benchmark。拿三条最慢的业务 SQL、两张最大的表,造一份接近生产分布的数据。跑单条,跑并发,跑一次故障切换。最后看扩容一次要多久。每一步都留记录,别只看一个总耗时。

故障切换也要拆开看。正在跑的查询会不会整体失败,重试能不能只补失败的分片。扩容要问清一次多久,重分布期间线上查询会不会被拖慢。这些比峰值数字更接近生产。

维度 要问的问题
数据量 现在多大,一年后多大,单表最大多少
查询复杂度 多表 join、窗口函数、聚合多不多
并发 同时跑多少条,峰值多少
更新频率 批量导入还是频繁更新
事务要求 要不要跨节点事务,一致性要求多高
运维 监控、备份、扩容、故障恢复怎么做
成本 硬件、软件、人力、扩容怎么算

并发这一项最容易漏。十条大查询一起跑,会不会互相拖死。有没有资源队列、内存配额、查询优先级。这些在单条 benchmark 里看不出来,在生产里天天遇到。

金仓 KADB 可以放进 POC 清单。它的定位是分析型负载。优势在大表扫描、复杂 join 和聚合的并行处理。国产化环境里的适配和本地服务,也是它会被考虑的原因。具体版本能力以手册为准。POC 跑完,再谈选谁。

数据倾斜排查避坑清单:低基数列、平均值与依赖

先说最容易忽略的。别拿低基数列做分布键。状态位、性别、地区码,看着均匀,业务一偏就倾斜。我们有张表用 status 做键。上线三个月,大半的行挤在一个值上,查一次卡一次。

还有个习惯要改,别只看平均。平均值看着不高,可能掩盖一个接近跑满的节点。看最慢节点,看每个 stage 的耗时分布,比看总耗时有用。

改键前一定要查依赖。视图、物化视图、索引、同步链路,一个都别漏。我那次就是漏了物化视图。后来我把依赖检查写进变更单,这条坑才算堵上。

写在最后:先看数据分布,再谈扩容

三步就够用。先用 SQL 看数据落在哪。再看执行计划里有没有重分布。最后才轮到加机器。产品会换,视图名会变,判断顺序不会变。

你们现在这套 MPP,最慢节点和最快节点差多少?差得离谱的话,先别扩容,去看看分布键。

我是数据库小学妹,帮你少走弯路少踩坑,咱们下篇见👋

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。