Skip to content

MPP:达梦的大规模并行处理架构

如果你的数据量从 1 亿增长到 100 亿,单机数据库已经跑不动了,怎么办?

加内存?加 CPU?加磁盘?

对不起,这是单机扩展的瓶颈。真正的答案是:横向扩展(Scale Out),而不是纵向扩展(Scale Up)。

达梦的 MPP(Massively Parallel Processing,大规模并行处理) 架构,就是为这种场景而生。

MPP 是什么?

MPP 是将多个数据库节点组成集群,协同处理大规模数据查询的计算模式。

传统单机:
                    ┌─────────────────┐
                    │   单机数据库    │
                    │  ┌───────────┐  │
                    │  │   所有    │  │
                    │  │   数据    │  │
                    │  └───────────┘  │
                    └─────────────────┘

MPP 集群:
     ┌──────────┬──────────┬──────────┐
     │ 节点1    │ 节点2    │ 节点3    │     ┌──────────┐
     │ 数据分片1│ 数据分片2│ 数据分片3│     │ 控制节点  │
     │  CPU1   │  CPU2   │  CPU3   │────▶│(EP/CN)   │
     │  内存1  │  内存2  │  内存3  │     └──────────┘
     └──────────┴──────────┴──────────┘
            ↓              ↓              ↓
         数据分片1      数据分片2      数据分片3

MPP 的核心概念

EP(Executive Coordinator,查询协调节点)

负责接收 SQL 请求,生成执行计划,协调各数据节点并行计算。

sql
-- EP 节点接收查询请求
SELECT customer_name, SUM(order_amount)
FROM orders
JOIN customers ON orders.cust_id = customers.id
WHERE order_date >= '2024-01-01'
GROUP BY customer_name;

DN(Data Node,数据节点)

存储实际数据,执行本地查询。每个 DN 拥有部分数据(数据分片)。

ini
# dmmpp.ini 配置
[GRP1]
EP_ADDRS = 192.168.1.10:5236,192.168.1.11:5236
MAL_INST_DUMP_FLAG = 1
MPP_SEQNO = 0

数据分布策略

哈希分布(Hash Distribution)

按指定列的哈希值分布数据。

sql
-- 创建哈希分布表
CREATE TABLE orders (
    order_id BIGINT,
    cust_id BIGINT,
    order_amount DECIMAL(10,2),
    ...
)
DISTRIBUTE BY HASH(cust_id);  -- 按客户ID哈希分布
cust_id = 1001 → hash(1001) = 5 → DN2
cust_id = 1002 → hash(1002) = 3 → DN1
cust_id = 1003 → hash(1003) = 5 → DN2
同一客户的数据在同一节点

复制分布(Replicate Distribution)

小表复制到所有节点,避免跨节点关联。

sql
-- 地区表复制到所有节点
CREATE TABLE region (
    region_id INT,
    region_name VARCHAR(50)
)
DISTRIBUTE BY REPLICATION;  -- 全量复制

随机分布(Random Distribution)

数据随机分布到各节点。

sql
-- 创建随机分布表
CREATE TABLE logs (
    log_id BIGINT,
    log_content TEXT
)
DISTRIBUTE BY ROUNDROBIN;  -- 轮询分布

MPP 查询执行流程

java
// MPP 查询执行流程
public class MppQueryFlow {

    public void queryExecution(String sql) {
        // 1. 客户端连接到 EP 节点
        Connection epConnection = getEpConnection();

        // 2. EP 解析 SQL,生成并行执行计划
        // SELECT cust_name FROM orders o, customers c WHERE o.cust_id = c.id
        // 执行计划:
        //   - 全局聚合(GATHER)
        //   - 本地聚合(LOCAL AGGREGATE)
        //   - 分布式 JOIN

        // 3. EP 将任务分发到各个 DN
        // DN1: 本地查询 + 本地聚合
        // DN2: 本地查询 + 本地聚合
        // DN3: 本地查询 + 本地聚合

        // 4. 各 DN 并行执行
        // 5. 结果汇总到 EP
        // 6. EP 返回最终结果
    }
}

MPP vs 单机 vs 集群

特性单机数据库主备集群MPP 集群
数据容量受单机磁盘限制受单机磁盘限制多机磁盘之和
查询性能单机 CPU/IO与单机相当多机并行,线性提升
并发能力受单机限制受主库限制多机并发
数据写入单点单点多节点可并行
适用场景中小型数据高可用需求大数据量
运维复杂度

MPP 的适用场景

适用场景

  • 数据仓库:TB/PB 级数据分析
  • OLAP 查询:复杂统计报表、多表关联
  • 日志分析:海量日志实时分析
  • ETL 处理:大规模数据抽取转换加载

不适用场景

  • OLTP 业务:高频小事务,单机足够
  • 强事务需求:跨节点事务性能差
  • 低延迟要求:MPP 查询延迟较高
java
// 判断是否适合 MPP
public class MppSuitability {

    public boolean isSuitableForMpp(Query query) {
        // 数据量小于 1 亿条,单机足够
        if (query.getDataSize() < 100_000_000) {
            return false;
        }

        // 复杂分析查询,适合 MPP
        if (query.isAnalytical() && query.getJoinCount() > 3) {
            return true;
        }

        // 高并发 OLTP,不适合
        if (query.getTps() > 1000 && query.isTransactional()) {
            return false;
        }

        return false;
    }
}

MPP 集群的运维

节点扩容

sql
-- 查看节点状态
SELECT
    GROUP_ID,
    EP_SEQUENCE,
    EP_NAME,
    EP_STATUS
FROM V$MPP_EP_INFO;

数据重分布

sql
-- 扩容后,需要重分布数据
ALTER TABLE orders REDISTRIBUTE BY HASH(cust_id);

跨节点查询优化

sql
-- 避免跨节点大表关联(性能差)
SELECT * FROM large_table1 t1
JOIN large_table2 t2 ON t1.id = t2.id  -- 两个大表 JOIN,跨节点开销大

-- 优化:先本地关联,再汇总
WITH local_result AS (
    SELECT cust_id, SUM(amount) as total
    FROM orders
    GROUP BY cust_id
)
SELECT c.name, r.total
FROM local_result r
JOIN customers c ON r.cust_id = c.id;

面试追问方向

  • MPP 和分库分表有什么区别?
  • MPP 中如何处理跨节点 JOIN?
  • MPP 集群中某个节点故障会怎样?

一句话总结

MPP 是大数据量的「加速器」:多机并行、线性扩展。但它不是万能药,OLTP 场景下反而可能帮倒忙。选对场景,才能发挥 MPP 的真正实力。

基于 VitePress 构建