本文汇总了异步物化视图在构建、刷新、查询改写等方面的常见问题及解决方法。
构建和刷新
Q1:物化视图是如何判断需要刷新哪些分区的?
SelectDB内部会计算物化视图和基表的分区对应关系,并记录上次刷新成功后物化视图使用的基表分区版本。下次刷新时,会判断这些基表分区的版本是否发生变化,如果变化则触发对应分区的刷新。
如果业务上允许某个非分区表的变化不触发物化视图刷新,可以通过物化视图属性excluded_trigger_tables进行设置。
Q2:物化视图占用资源过多,影响其他业务怎么办?
可以通过物化视图属性指定workload_group来限制物化视图刷新任务的资源使用。注意:如果内存设置过小而单个分区刷新需要较多内存,任务会刷新失败,需根据业务情况权衡。
Q3:能基于物化视图创建新的物化视图吗?
能。SelectDB支持基于物化视图创建新的物化视图(嵌套物化视图)。但需注意:刷新数据时,每个物化视图采用独立的刷新逻辑,例如mv2基于mv1创建,刷新mv2时不会考虑mv1与基表的同步情况。
Q4:哪些外部数据源支持创建物化视图?
SelectDB支持的所有外表均可用于创建物化视图,但目前仅Hive支持分区增量刷新,其他类型外表(如Iceberg、JDBC等)需使用COMPLETE全量刷新。
Q5:物化视图显示和Hive数据一致,但实际上不一致?
物化视图仅保证数据与通过Catalog查询的结果一致。由于Catalog存在元数据和数据缓存,如果需要物化视图与Hive原始数据保持一致,需通过REFRESH CATALOG等方式确保Catalog数据与Hive数据同步后,再刷新物化视图。
Q6:物化视图支持Schema Change吗?
不支持直接修改物化视图的列定义,因为物化视图的列属性是根据定义SQL推导的。如需调整,需重建物化视图。
Q7:物化视图使用的基表允许Schema Change吗?
允许。但变更之后,使用到该基表的物化视图状态会从NORMAL变为SCHEMA_CHANGE,此时物化视图不能参与透明改写(但支持直查)。如果物化视图下次刷新任务成功,状态会恢复为NORMAL。
Q8:主键模型的表能用来创建物化视图吗?
能。物化视图对基表的数据模型没有要求,但物化视图本身只能是明细模型(Duplicate Key)。
Q9:物化视图上还能建索引吗?
能。
Q10:物化视图刷新的时候会锁表吗?
在很短的阶段会有锁表,但不会持续占用表锁(几乎等同于导入数据的锁表时间),不会影响正常查询。
Q11:物化视图适合近实时场景吗?
不太适合。物化视图刷新的最小单位是分区,数据量大时会占用较多资源,且实时性不够。近实时场景建议使用同步物化视图或其他实时更新手段。
分区物化视图问题
Q1:构建分区物化视图时报错"Unable to find a suitable base table for partitioning"怎么处理?
此报错表示物化视图的SQL定义和分区字段选择不满足分区增量更新要求。物化视图要支持分区增量更新,需满足以下条件:
物化视图的分区字段必须来源于基表的分区列,或基于分区列使用
date_trunc函数处理后的列。分区字段不能来源于LEFT JOIN中可能产生NULL值一侧的非分区列。
例如,在以下示例中,选择orders.o_orderdate作为分区字段是正确的,而选择lineitem.l_shipdate(非分区列,且是LEFT JOIN产生NULL的一侧)会导致报错:
-- 正确:使用orders表的分区列o_orderdate作为物化视图分区字段
CREATE MATERIALIZED VIEW mv_correct
BUILD IMMEDIATE REFRESH AUTO ON MANUAL
PARTITION BY (o_orderdate)
DISTRIBUTED BY RANDOM BUCKETS 2
AS SELECT l_linestatus, sum(l_extendedprice * (1 - l_discount)) AS revenue, o_orderdate
FROM orders LEFT JOIN lineitem ON l_orderkey = o_orderkey
GROUP BY l_linestatus, o_orderdate;Q2:创建物化视图时报错"BUILD IMMEDIATE REFRESH AUTO ON MANUAL Syntax error"怎么处理?
异步物化视图的语法仅在新优化器(Nereids)下支持,请确保已开启新优化器:
SET enable_nereids_planner = true;Q3:物化视图刷新成功后,还是没有数据?
可能原因:使用了不支持获取数据版本信息的数据源(如JDBC Catalog),导致刷新时认为无需更新。解决方法:刷新时指定COMPLETE全量刷新:
REFRESH MATERIALIZED VIEW mv_name COMPLETE;Q4:创建的是分区物化视图,为什么每次都是全量刷新?
可能原因:物化视图定义SQL中的非分区追踪表数据发生了变化,导致系统无法判断哪些分区需要增量更新,只能退化为全量刷新。
解决方法:
如果非分区表的变化对物化视图数据影响不大,可通过设置
excluded_trigger_tables属性来排除该表的变更触发。可通过以下SQL查看物化视图的分区追踪情况:
SELECT * FROM mv_infos('database'='db_name') WHERE Name = 'partition_mv' \G
查询和透明改写
Q1:如何确认查询是否命中了物化视图透明改写?
通过EXPLAIN查看查询计划,在输出中搜索以下标记:
MaterializedViewRewriteSuccessAndChose:改写成功且选择了该物化视图(已命中)。MaterializedViewRewriteSuccessButNotChose:改写成功但基于代价模型未选择该物化视图(说明有更优的执行计划)。MaterializedViewRewriteFail:改写失败,后跟失败原因摘要信息。
Q2:查询未命中物化视图透明改写,可能是什么原因?
常见原因包括:
开关未开启:确认
enable_materialized_view_rewrite和enable_nereids_planner均为true。物化视图状态不可用:物化视图状态不是NORMAL(可能是SCHEMA_CHANGE或刷新未成功)。通过
SELECT * FROM mv_infos('database'='db_name') WHERE Name = 'mv_name'查看状态。SQL模式不匹配:查询的SELECT/JOIN/GROUP BY/WHERE模式与物化视图定义不兼容。例如查询包含窗口函数、UNION ALL、CROSS JOIN等物化视图不支持透明改写的语法。
外表物化视图未开启改写:如果物化视图基于外表创建,需设置
SET materialized_view_rewrite_enable_contain_external_table = true。
Q3:物化视图状态从NORMAL变为其他状态的原因?
常见原因包括:
基表数据发生变更:物化视图的基表有新的导入、更新或删除操作,物化视图数据不再是最新的。
基表发生Schema Change:基表的列定义发生变更,物化视图状态会变为SCHEMA_CHANGE。
刷新任务失败:上一次刷新任务执行失败,物化视图数据未更新成功。
以上情况均可在下次刷新任务成功后自动恢复为NORMAL状态。
Q4:直查物化视图返回无数据?
可能原因:物化视图刚创建且设置了BUILD DEFERRED(延迟刷新),或上次刷新任务失败。可通过以下方式排查:
-- 查看刷新任务状态
SELECT * FROM tasks('type'='mv') WHERE MvName = 'mv_name' ORDER BY CreateTime DESC LIMIT 1;如确认物化视图数据为空,可手动触发刷新:REFRESH MATERIALIZED VIEW mv_name COMPLETE;
Q5:基表数据变更后,物化视图还没刷新,这时候查询走透明改写会返回旧数据吗?
取决于grace_period属性和enable_materialized_view_union_rewrite配置:
如果设置了
grace_period且在允许的滞后时间内,物化视图仍参与透明改写,可能返回非最新数据。如果
grace_period为0(默认),基表变更后物化视图会退出透明改写候选。对于分区物化视图,如果
enable_materialized_view_union_rewrite = true(默认),查询可以合并物化视图有效分区的数据和基表最新分区的数据,保证结果正确性。