3、Doris核心原理:MPP架构、物化视图、Rollup表、Bucket分桶策略

聊到Doris,很多人第一反应是「快」。但为什么快?底层到底干了什么?

我刚开始接触Doris时,也踩过不少坑。那时候光顾着建表导数据,结果查询慢得离谱。后来才明白——不理解MPP、物化视图、Rollup和分桶策略,你根本驾驭不了Doris。

今天咱们就把这几个核心概念掰开揉碎,讲清楚。

3.1 MPP架构:并行计算的「流水线工厂」

MPP,全称Massively Parallel Processing,说白了就是「多台机器一起干活」。但关键在于——怎么分活、怎么汇总。

核心思想:Doris把一个大查询拆成多个小任务,分发到不同节点并行执行。每个节点只处理自己那一份数据,最后汇总结果。

我举个例子。假设你要统计全国所有门店的日销售额。单机版就是一个人跑遍所有门店,累死。MPP版呢?每个门店派一个人,算完自己门店的,最后报个数上来。

Doris的MPP架构分三层:

  • FE(Frontend): 负责接收SQL、生成执行计划、调度任务。相当于「包工头」。
  • BE(Backend): 负责实际存储和计算。相当于「干活的人」。
  • Broker(可选): 负责跟外部存储(如HDFS、S3)打交道。

这里有个关键点——FE不存数据,只存元数据。所以FE挂了不影响数据,但查询会中断。我建议生产环境至少部署3个FE节点,用Follower/Observer模式保证高可用。

避坑指南:我曾经遇到一个案例,FE节点内存配小了,结果元数据一多就OOM。Doris的FE对内存要求不低,尤其是表数量上千时。建议至少16GB起步。

MPP的查询流程大致如下:

  1. 客户端发SQL给FE。
  2. FE解析SQL,生成执行计划,拆成多个Fragment。
  3. FE把Fragment分发给BE节点。
  4. BE并行执行,每个节点只处理自己负责的数据分片。
  5. BE把中间结果汇总回FE(或直接返回客户端)。

你想想看,如果数据量是100TB,单机跑一个聚合查询可能要几个小时。但Doris用100台机器并行,理论上几分钟就能搞定。这就是MPP的魅力。

3.2 物化视图:用空间换时间的「预计算」

物化视图,名字听着高大上,其实本质就是把查询结果提前算好存起来。

我刚开始用Doris时,总觉得物化视图跟普通视图差不多。后来发现完全不是一回事——普通视图只是个壳,物化视图是真存数据。

适用场景:高频查询、固定维度的聚合计算。比如每天统计「每个省份的销售额」,这种查询如果每次都全表扫描,效率极低。建个物化视图,数据写入时自动算好,查询时直接读结果。

Doris的物化视图有几个特点:

  • 自动维护: 基表数据变更时,物化视图自动更新。不需要你手动刷。
  • 透明查询: 查询时Doris自动匹配最优的物化视图,不需要改SQL。
  • 支持多种聚合: SUM、COUNT、MAX、MIN、AVG等。

举个例子:

-- 创建基表
CREATE TABLE sales (
    province VARCHAR(20),
    city VARCHAR(20),
    amount BIGINT
) DISTRIBUTED BY HASH(province) BUCKETS 10;

-- 创建物化视图:按省份聚合
CREATE MATERIALIZED VIEW mv_province_sales AS
SELECT province, SUM(amount) AS total_amount
FROM sales
GROUP BY province;

之后你查SELECT province, SUM(amount) FROM sales GROUP BY province,Doris会自动走物化视图,而不是扫全表。

注意:物化视图不是越多越好。每建一个,写入时就要多维护一份数据。我见过有人建了十几个物化视图,结果写入性能暴跌。建议只对核心查询建物化视图,一般不超过5个。

3.3 Rollup表:多维分析的「降维打击」

Rollup表,很多人把它跟物化视图搞混。其实两者有本质区别——物化视图是「预计算」,Rollup是「预聚合+预排序」。

说白了,Rollup就是Doris里的一种特殊索引。它把数据按不同维度组合预先聚合好,查询时直接命中对应的Rollup,避免全表扫描。

核心逻辑:Doris的Base表存最细粒度的数据。Rollup表存粗粒度的聚合数据。查询时自动匹配最优的Rollup。

举个例子。假设Base表有4个维度列:province, city, district, street。你可以建以下Rollup:

Rollup名称 维度组合 数据量 适用查询
Base表 province, city, district, street 100% 最细粒度查询
Rollup_1 province, city, district ~20% 按区统计
Rollup_2 province, city ~5% 按市统计
Rollup_3 province ~1% 按省统计

查询SELECT SUM(amount) FROM sales WHERE province='广东'时,Doris会直接走Rollup_3,只扫1%的数据。快不快?

个人经验:我习惯把Rollup理解为「查询加速器」。建Rollup时,先分析业务查询的WHERE条件和GROUP BY字段,然后按「最常用维度组合」来建。别贪多,一般3-5个Rollup就够了。

Rollup的创建语法:

-- 创建Rollup
ALTER TABLE sales ADD ROLLUP rollup_city (province, city);

-- 查看Rollup
SHOW ALTER TABLE ROLLUP;

嗯,这里要注意——Rollup的列顺序很重要。Doris按前缀匹配原则选择Rollup。比如Rollup是(province, city),那查询条件必须包含province才能命中。如果只查city,就匹配不上。

3.4 Bucket分桶策略:数据分布的「分而治之」

分桶,就是决定数据在BE节点上怎么分布。分得好,查询快;分不好,数据倾斜,查询慢如蜗牛。

Doris支持两种分桶方式:

  • Hash分桶: 按某个字段的哈希值取模,均匀分布。
  • Random分桶: 随机分布,适合无合适分桶键的场景。

核心原则:分桶键要选高基数、分布均匀的字段。比如用户ID、订单ID。别选性别、省份这种低基数字段,否则数据全挤在几个桶里。

分桶数怎么定?我有个经验公式:

分桶数 = BE节点数 × 每个节点的CPU核数 × 2~3

举个例子,10台BE,每台16核,那分桶数可以设为10 × 16 × 2 = 320。这样每个BE分到32个桶,并行度刚好。

踩坑记录:我曾经把分桶数设得特别大(比如1000个桶),结果每个桶数据量太小,查询时调度开销反而比计算开销还大。分桶不是越多越好,建议每个桶的数据量在1GB~10GB之间。

分桶的创建语法:

CREATE TABLE sales (
    order_id BIGINT,
    province VARCHAR(20),
    amount BIGINT
) DISTRIBUTED BY HASH(order_id) BUCKETS 32;

分桶策略选得好不好,直接影响查询性能。我建议你在建表前先做个小测试——用SELECT COUNT(DISTINCT 分桶键) FROM 表看看基数。基数越高,分桶效果越好。

3.5 知识体系总览

下面这张图,把MPP、物化视图、Rollup、分桶的关系串起来了。你可以把它当个「脑图」用。

Doris核心原理知识体系 Doris 核心原理 MPP 并行架构 物化视图 Rollup 表 Bucket 分桶 FE 调度 BE 计算 预计算 自动维护 预聚合 前缀匹配 Hash分布 数据倾斜 MPP提供并行能力,物化视图和Rollup加速查询,分桶保证数据均匀分布

总结一下:MPP是骨架,物化视图和Rollup是加速器,分桶是数据分布的基石。这四个东西搞明白了,Doris的查询优化你就掌握了80%。

最后一个小建议:别一上来就搞复杂的物化视图和Rollup。先建个简单的表,跑几个查询看看性能。然后逐步加物化视图、Rollup,对比效果。实践出真知。