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
物化视图解决的问题是: 把高成本计算提前做掉, 让查询读更少的数据或更接近目标形态的数据。
参考:
- https://doris.apache.org/docs/4.x/query-acceleration/materialized-view/overview/
- https://doris.apache.org/docs/4.x/query-acceleration/materialized-view/async-materialized-view/overview/
- https://doris.apache.org/docs/4.x/query-acceleration/sql-cache-manual/
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 能不能被改写, 看四件事:
- MV 是否包含查询所需列。
- MV 的过滤范围是否覆盖查询范围。
- 聚合粒度是否能 roll-up 到查询粒度。
- 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 Cache | MV 稳定预聚合 |
| 高选择性等值过滤 | Sort Key / Bloom | Inverted Index |
| 文本检索 | Inverted Index | 结果 MV |
| 大表 Join | Colocate / Broadcast | 异步 MV |
| 湖仓热数据 | Data Cache | 外表 MV |
| TopN | TopN 优化 | 排序键和小 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 的物化视图不是"多建一张快表", 而是把查询成本、刷新成本、数据一致性和资源隔离放到同一个设计里权衡。