异步物化视图概述
异步物化视图是一种兼具视图灵活性与物理表高性能的查询加速方案。它通过预先计算并存储查询结果,使后续查询能直接命中已物化的结果集,避免重复执行复杂 SQL 带来的开销。
快速导览
在开始使用异步物化视图前,建议先确认以下要点:
- 业务是否需要查询加速、ETL 简化、湖仓外表加速或写入优化?
- 查询是否符合 SPJG(SELECT-PROJECT-JOIN-GROUP-BY)模式?
- 数据是否可以接受最终一致性(非实时同步)?
- 基表所在的 Catalog 是否在受支持范围内(Internal/Hive/Iceberg/Paimon/Hudi/JDBC/ES)?
- 是否需要分区增量刷新以降低刷新成本?
使用场景
异步物化视图主要面向以下四类场景:
| 场景 | 价值 |
|---|---|
| 查询加速与并发提升 | 显著提高查询速度,增强并发能力,减少资源消耗 |
| 简化 ETL 流程 | 在抽取、转换、加载(ETL)过程中简化流程,提升开发效率 |
| 加速湖仓一体外表查询 | 在湖仓一体架构中显著提升对外部数据源的查询速度 |
| 提升写入效率 | 减少资源竞争,优化数据写入过程,保障一致性与完整性 |
使用限制
使用异步物化视图前,需了解以下限制:
- 数据一致性:异步物化视图与基表的数据最终一致,但无法实时同步,不保证实时一致性。
- 窗口函数:当前若查询包含窗口函数,暂不支持透明改写为基于物化视图的形式。
- 多表场景:如果物化视图所连接的表数量多于查询所涉及的表(例如查询仅涉及 t1、t2,而物化视图包含 t1、t2、t3),则当前不支持透明改写。
- 不支持透明改写的算子:如果物化视图包含
UNION ALL、LIMIT、ORDER BY、CROSS JOIN,物化视图可正常构建,但不能用于透明改写。 - 数据类型限制:创建物化视图暂不支持
VARBINARY类型。
原理介绍
异步物化视图本质上是类型为 MTMV 的内表。创建物化视图时,系统会同时注册一个刷新任务;任务运行时通过 INSERT OVERWRITE 语句将最新数据写入物化视图。
刷新机制
异步物化视图与同步物化视图的实时增量刷新不同,提供了更灵活的刷新选项:
| 刷新模式 | 说明 | 适用场景 |
|---|---|---|
| 全量刷新 | 重新计算物化视图定义 SQL 涉及的所有数据,并完整写入物化视图 | 数据量较小或需要保证整体一致性 |
| 分区增量刷新 | 智能识别基表分区数据的变化,仅刷新受影响的分区 | 数据量较大、变化集中在部分分区 |
- 全量刷新:确保物化视图数据与基表完全一致,但可能消耗较多计算资源与时间。
- 分区增量刷新:显著降低刷新所需的资源与时间,并保证最终一致性。
透明改写
透明改写是数据库优化查询性能的一种重要手段。系统在处理用户查询时会自动改写 SQL,命中合适的物化视图,从而提升执行效率、降低计算成本。整个过程对用户透明,无需任何干预。
Doris 异步物化视图采用基于 SPJG(SELECT-PROJECT-JOIN-GROUP-BY)模式的透明改写算法:
- 深入分析 SQL 的结构信息。
- 自动寻找并选择合适的物化视图进行透明改写。
- 当存在多个候选物化视图时,依据成本模型等策略选择最优物化视图响应查询,进一步提升性能。
基于数据湖创建异步物化视图
基于数据湖创建异步物化视图的语法与基于内表完全一致,但需注意以下事项:
- 元数据来源:物化视图刷新所需的分区版本等信息来自数据湖的元数据缓存,并非直接从外部环境获取。因此刷新完成后,数据与通过 Doris 查询数据湖的结果一致,但可能与其它引擎查询结果不一致,具体取决于缓存的刷新情况。
- 外部变更感知:如果 Hive 底层数据通过非 Doris 控制的外部流程(如 Spark、Hive 或 Flink 作业)发生变更但元数据未变(例如执行
insert overwrite),物化视图会误认为与基表一致,但查询结果会与 Doris 查询数据湖的结果不一致。可通过手动强制刷新物化视图解决此问题。 - Iceberg 限制:基于 Iceberg 创建分区物化视图时,仅支持 Iceberg 表分区列只有一列的情况,并有限度支持分区演进——例如时间类型分区时间范围变化是支持的;如果分区字段本身发生变化,则物化视图刷新会失败。
- Hudi 限制:基于 Hudi 创建物化视图时,无法感知基表数据是否发生变化。只要刷新过物化视图(或其部分分区),就会认为与基表同步,因此基于 Hudi 创建物化视图仅适用于手动按需刷新场景。
物化刷新数据湖支持情况
不同表类型与 Catalog 的刷新支持程度如下:
| 表类型 | Catalog 类型 | 刷新方式 | 刷新时机 | |
|---|---|---|---|---|
| 全量刷新 | 分区刷新 | 自动触发 | ||
| 内表 | Internal | 2.1 支持 | 2.1 支持 | 2.1.4 支持 |
| Hive | Hive | 2.1 支持 | 2.1 支持 | 不支持 |
| Iceberg | Iceberg | 2.1 支持 | 3.1 支持 | 不支持 |
| Paimon | Paimon | 2.1 支持 | 3.1 支持 | 不支持 |
| Hudi | Hudi | 2.1 支持 | 3.1 支持 | 不支持 |
| JDBC | JDBC | 2.1 支持 | 不支持 | 不支持 |
| ES | ES | 2.1 支持 | 不支持 | 不支持 |
透明改写数据湖支持情况
异步物化视图的透明改写功能目前支持以下表类型与 Catalog。
实时感知基表数据:指物化视图使用的基表数据发生变化时,物化视图能实时感知并在查询中使用最新数据。
| 表类型 | Catalog 类型 | 透明改写支持 | 实时感知基表数据 |
|---|---|---|---|
| 内表 | Internal | 支持 | 支持 |
| Hive | Hive | 支持 | 3.1 支持 |
| Iceberg | Iceberg | 支持 | 3.1 支持 |
| Paimon | Paimon | 支持 | 3.1 支持 |
| Hudi | Hudi | 支持 | 不支持 |
| JDBC | JDBC | 支持 | 不支持 |
| ES | ES | 支持 | 不支持 |
开启外表物化视图的透明改写
物化视图使用外表时,默认不参与透明改写。如需开启,可执行:
SET materialized_view_rewrite_enable_contain_external_table = true;
外表透明改写性能优化
自 2.1.11 起,Doris 优化了外表的透明改写性能,主要改进了获取包含外表的可用物化视图的性能。
如果包含外表的分区物化视图透明改写较慢,可在 fe.conf 中调整以下参数:
| 参数 | 默认值 | 说明 | 版本 |
|---|---|---|---|
max_hive_partition_cache_num | 10000 | Hive Metastore 表级别分区缓存的最大数量;Hive 外表分区较多时建议设置为 20000 或更大 | - |
external_cache_expire_time_minutes_after_access | 10 分钟 | 缓存对象自最后一次访问后的失效时间,可适当调长(适用于外表 schema 缓存与 Hive 元数据缓存) | - |
external_cache_refresh_time_minutes | 10 分钟 | 外部表元数据缓存对象的自动刷新时间,可适当调长 | 3.1+ |
外表元数据缓存的更多配置详情,参见 元数据缓存。
物化视图与 OLAP 内表的关系
异步物化视图定义 SQL 使用的基表模型不受限制,可以是明细模型、主键模型(merge-on-write 与 merge-on-read)、聚合模型等。
物化视图自身的底层实现依托于 Duplicate 模型的 OLAP 表,理论上能够支持 Duplicate 模型的所有核心功能。但为了保障物化视图能够稳定且高效地执行数据刷新任务,对其功能进行了一系列必要限制:
- 分区操作:物化视图的分区基于其基表自动创建和维护,用户不能对物化视图进行分区操作。
- 删除与重命名:由于物化视图背后存在相关的作业(JOB),不能使用
DELETE TABLE或RENAME TABLE命令操作物化视图,需使用物化视图自身的命令完成对应操作。 - 列数据类型:物化视图的列数据类型由创建时指定的查询语句自动推导,不能修改,否则可能导致刷新任务失败。
- 属性修改:物化视图具有一些 Duplicate 表没有的属性(property),需通过物化视图的命令修改;其他公用属性则使用
ALTER TABLE命令修改。
常见问题
Q1:异步物化视图能保证与基表数据实时一致吗?
不能。异步物化视图与基表的数据最终一致,但无法实时同步。如需实时一致性,请考虑同步物化视图。
Q2:查询包含窗口函数时为什么无法被改写?
当前透明改写算法尚未支持窗口函数,包含窗口函数的查询不会被改写为基于物化视图的形式。
Q3:基于外表的物化视图为什么没有命中改写?
外表的物化视图默认不参与透明改写。需设置 materialized_view_rewrite_enable_contain_external_table = true 后才会参与改写。
Q4:Hive 外表数据被外部流程修改后,为什么物化视图查询结果不一致?
如果通过 Spark/Hive/Flink 等外部流程修改了 Hive 数据但元数据未变(例如 insert overwrite),物化视图无法感知变化。可通过手动强制刷新物化视图解决。
Q5:基于 Hudi 的物化视图能自动刷新吗?
不能感知基表变化,仅适用于手动按需刷新场景。
更多参考
- 创建、查询与维护异步物化视图:创建、查询与维护异步物化视图
- 使用指南:使用指南
- 常见问题:常见问题