Doris architecture

ANALYTICAL DATABASE / SOURCE READING / LESSON 19

Materialized views and query acceleration

Design query acceleration with synchronous rollups, async materialized views, transparent rewrite, refresh strategy, and resource isolation.

Reading
55 min
Track
Doris architecture
Source
Chinese source notes

The source notes for this track are currently maintained in Chinese.

预计阅读时间: 55 分钟 前置阅读: doc-03, doc-08, doc-18 下一次阅读: doc-20(实时写入、更新与删除)


1. 加速手段不是只有索引

Doris 查询加速可以分成五层:

表设计: Partition / Bucket / Sort Key
  → 存储索引: Prefix / ZoneMap / Bloom / Bitmap / Inverted
    → 物化视图: 同步 Rollup / 异步 MV / 透明改写
      → 缓存: SQL Cache / Condition Cache / Data Cache
        → 执行调优: RuntimeFilter / Join / TopN / Spill / Workload Group

物化视图解决的问题是: 把高成本计算提前做掉, 让查询读更少的数据或更接近目标形态的数据。

参考:


2. 同步物化视图: 表内 Rollup 思路

同步物化视图更接近传统 Rollup。它跟随基表写入同步维护, 适合单表聚合和排序前缀优化。

示例:

CREATE MATERIALIZED VIEW mv_event_service_daily AS
SELECT
    date_trunc(event_time, 'day') AS dt,
    tenant_id,
    service_name,
    count(*) AS cnt
FROM event_log
GROUP BY
    date_trunc(event_time, 'day'),
    tenant_id,
    service_name;

适合:

  • 单表聚合。
  • 高频 dashboard 查询。
  • 聚合维度稳定。
  • 可接受写入时维护成本。

不适合:

  • 多表 Join 很复杂。
  • 刷新窗口需要独立控制。
  • 基表更新频繁且视图维护成本过高。

3. 异步物化视图: 更像可管理的数据产品

异步物化视图可以独立刷新, 支持更复杂 SQL 和分区增量刷新。它更适合专家级场景:

  • 多表 Join 预计算。
  • 明细到宽表或汇总表。
  • 湖仓外表加速。
  • 多层指标模型。
  • 生产报表稳定加速。

示例:

CREATE MATERIALIZED VIEW mv_order_user_daily
BUILD IMMEDIATE
REFRESH AUTO ON MANUAL
PARTITION BY(dt)
DISTRIBUTED BY HASH(tenant_id) BUCKETS 24
AS
SELECT
    o.dt,
    o.tenant_id,
    u.city,
    count(*) AS order_cnt,
    sum(o.amount) AS amount
FROM fact_order o
JOIN dim_user u ON o.user_id = u.user_id
GROUP BY o.dt, o.tenant_id, u.city;

设计重点:

维度判断
刷新模式全量、分区增量、手动还是定时
分区对齐MV 分区能否映射基表分区
查询改写目标 SQL 是否符合可改写形态
资源隔离刷新是否放进独立 Workload Group
可用性刷新失败时是否允许读旧数据

4. 透明改写怎么理解

透明改写是指用户仍然查原 SQL, 优化器自动改写到物化视图。

用户 SQL
  → Nereids 解析逻辑计划
    → 匹配可用 MV
      → 判断字段、谓词、聚合、分区有效性
        → 选择成本更低的 MV 计划

判断一个 SQL 能不能被改写, 看四件事:

  1. MV 是否包含查询所需列。
  2. MV 的过滤范围是否覆盖查询范围。
  3. 聚合粒度是否能 roll-up 到查询粒度。
  4. Join 关系是否能表达同样语义。

反例:

-- MV 只有 dt, tenant_id 粒度
-- 查询要求 trace_id 明细, 不能从 MV 还原
SELECT trace_id
FROM event_log
WHERE dt = '2026-07-27';

5. 刷新策略

全量刷新

适合:

  • 数据量小。
  • 逻辑简单。
  • 作为早期验证。

风险:

  • 数据增长后刷新时间线性变长。
  • 刷新资源与在线查询竞争。

分区增量刷新

适合:

  • 时间分区事实表。
  • 每天或每小时新增数据。
  • 基表分区与 MV 分区能映射。

关键:

  • 分区列表达式要稳定。
  • 迟到数据要有补刷策略。
  • 历史分区修正要可手工触发。

嵌套物化视图

适合复杂指标分层:

明细表
  → 日级服务指标 MV
    → 租户级周报 MV
      → 产品看板查询

风险:

  • 依赖链变长。
  • 上游刷新失败影响下游。
  • 需要明确血缘和告警。

6. MV 与 Workload Group

物化视图刷新本质上也是查询和写入任务。生产环境必须把刷新资源管起来。

-- 思路示例: 为 MV 刷新准备独立资源组
CREATE WORKLOAD GROUP mv_refresh
PROPERTIES (
    "cpu_share" = "512",
    "memory_limit" = "30%"
);

然后在物化视图属性或调度层把刷新任务放到指定资源组。资源太小会导致刷新失败, 太大会挤压在线查询。专家要按刷新窗口、数据量和 SLA 做压测。


7. 与其他加速能力组合

目标首选补充
重复 dashboard 查询SQL CacheMV 稳定预聚合
高选择性等值过滤Sort Key / BloomInverted Index
文本检索Inverted Index结果 MV
大表 JoinColocate / Broadcast异步 MV
湖仓热数据Data Cache外表 MV
TopNTopN 优化排序键和小 LIMIT

不要用 MV 掩盖所有问题:

  • 如果基表分区错误, MV 只是在复制问题。
  • 如果查询模式很分散, MV 维护成本可能高于收益。
  • 如果数据实时性要求极高, 刷新延迟需要写进 SLA。

8. 验证 MV 是否真的有效

验证步骤:

EXPLAIN SELECT ...;

看计划是否命中物化视图。然后开启 Profile 对比:

SET enable_profile = true;
SELECT ...;
SHOW PROFILELIST;
SHOW PROFILE WHERE query_id = '...';

对比指标:

指标期望
扫描行数明显下降
Scan 时间明显下降
Join/聚合时间被提前计算或降低
总耗时稳定下降
刷新耗时在窗口内
刷新资源不影响在线查询

9. 专家级 MV 设计模板

1. 目标 SQL: 哪些 SQL 或报表要加速
2. 基表模型: 分区、分桶、排序键、数据量
3. 查询共性: 过滤列、Join、Group By、时间窗口
4. MV 定义: 列、粒度、分区、分桶
5. 刷新策略: 全量/增量/手动/定时
6. 资源隔离: Workload Group 与刷新窗口
7. 正确性: 迟到数据、历史修正、失败重试
8. 观测: 刷新耗时、失败率、命中率
9. 回滚: 删除 MV 后原 SQL 是否可接受

一句话总结:

Doris 的物化视图不是"多建一张快表", 而是把查询成本、刷新成本、数据一致性和资源隔离放到同一个设计里权衡。