StarRocks `inspect_mv_plan` 函数完全指南:查看物化视图逻辑执行计划与计划缓存行为

发布时间:2026/9/19 12:20:49
StarRocks `inspect_mv_plan` 函数完全指南:查看物化视图逻辑执行计划与计划缓存行为
StarRocksinspect_mv_plan函数完全指南查看物化视图逻辑执行计划与计划缓存行为【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocksinspect_mv_plan是 StarRocks FE 提供的内置元数据函数meta function用于以字符串形式返回指定异步物化视图Async Materialized View的逻辑执行计划logical plan并可选地读取物化视图计划缓存。在排查物化视图查询改写query rewrite未命中、验证基于视图的物化视图计划形态、理解计划缓存命中与失效机制等场景中它是开发者和 DBA 的高效诊断工具。读完本文你将掌握该函数的完整语法、输出解读、底层实现原理以及与之相关的会话变量与 FE 配置项。函数概览与适用场景inspect_mv_plan的核心作用是把一个物化视图的定义 SQL 经优化器生成的逻辑计划树以人类可读的字符串形式输出。它属于 StarRocks 的 meta-functions 家族与inspect_mv_meta、inspect_mv_refresh_info、inspect_related_mv等函数互补前者输出“物化视图长什么样、依赖什么”后者输出“物化视图在优化器中会被改写成什么样的逻辑计划”。典型使用场景包括排查物化视图改写失效当一条查询没有命中预期中的物化视图时先用inspect_mv_plan确认该物化视图的逻辑计划是否如预期生成验证视图之上建物化视图当物化视图基于普通视图view创建时优化器可能产生多个候选逻辑计划是否内联展开视图该函数会一次性全部返回评估计划缓存收益通过use_cache参数对比走缓存与不走路缓存的计划获取行为验证缓存是否命中、是否需要重建。函数语法inspect_mv_plan提供两个重载签名inspect_mv_plan(mv_name) inspect_mv_plan(mv_name, use_cache)两者都返回物化视图的逻辑计划。参数说明参数类型是否必填说明mv_nameVARCHAR是物化视图名称支持db.mv_name形式的全限定名use_cacheBOOLEAN否是否使用物化视图计划缓存默认值为TRUE在 FE 源码中这两个重载对应 MetaFunctions.java 中的两个ConstantFunction声明ConstantFunction(name inspect_mv_plan, argTypes {VARCHAR}, returnType VARCHAR, isMetaFunction true) public static ConstantOperator inspectMvPlan(ConstantOperator mvName) { return inspectMvPlan(mvName, ConstantOperator.TRUE); } ConstantFunction(name inspect_mv_plan, argTypes {VARCHAR, BOOLEAN}, returnType VARCHAR, isMetaFunction true) public static ConstantOperator inspectMvPlan(ConstantOperator mvName, ConstantOperator useCache) { ... }可以看到单参数版本等价于显式传入use_cache TRUE即默认行为是优先读取计划缓存。返回值逻辑计划的字符串表示函数返回一个 VARCHAR 字符串其中包含该物化视图的全部逻辑计划。对于大多数普通物化视图只输出一个plan 0而当物化视图基于普通视图创建时优化器可能产生“内联视图”与“不内联视图”两种候选计划此时会依次输出plan 0、plan 1……这一点在CachingMvPlanContextBuilder的源码注释中有明确说明After view-based mv rewrite, one mv may has views as based tables, It can return logical plans with or without inline views. So here should return aListMvPlanContextfor one mv.计划输出格式解读以文档中的示例输出为例plan 0: LogicalAggregation {typeGLOBAL ,aggregations{3: sumsum(2: pv)} ,groupKeys[1: event_day] ,projectionnull ,predicatenull} - LogicalOlapScanOperator {table28673, selectedPartitionIdnull, selectedIndexId28674, outputColumns[1: event_day, 2: pv], predicatenull, prunedPartitionPredicates[], limit-1} plan 1: LogicalViewScanOperator {tableview1, outputColumns[4: event_day, 5: sum_pv]}关键字段含义LogicalAggregation物化视图定义中的聚合操作aggregations{3: sumsum(2: pv)}表示输出列 3 由列 2pv求sum得到groupKeys[1: event_day]表示按event_day分组projection/predicate为空表示没有额外投影与过滤。LogicalOlapScanOperator底层的 OLAP 表扫描算子table28673为表 IDselectedIndexId28674为选中的索引Tablet 元数据IDoutputColumns[1: event_day, 2: pv]为输出列prunedPartitionPredicates为空表示没有分区裁剪谓词limit-1表示无 limit。LogicalViewScanOperator视图扫描算子tableview1表示扫描的视图名outputColumns[4: event_day, 5: sum_pv]为该视图的输出列。出现该算子说明这是“未内联视图”的候选计划。使用示例示例一使用计划缓存查看逻辑计划mysql select inspect_mv_plan(mv_on_view_1); ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | inspect_mv_plan(mv_on_view_1) | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | plan 0: LogicalAggregation {typeGLOBAL ,aggregations{3: sumsum(2: pv)} ,groupKeys[1: event_day] ,projectionnull ,predicatenull} - LogicalOlapScanOperator {table28673, selectedPartitionIdnull, selectedIndexId28674, outputColumns[1: event_day, 2: pv], predicatenull, prunedPartitionPredicates[], limit-1} plan 1: LogicalViewScanOperator {tableview1, outputColumns[4: event_day, 5: sum_pv]} | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 row in set (0.01 sec)示例二不使用计划缓存查看逻辑计划mysql select inspect_mv_plan(mv_on_view_1, false); ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | inspect_mv_plan(mv_on_view_1, FALSE) | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | plan 0: LogicalAggregation {typeGLOBAL ,aggregations{3: sumsum(2: pv)} ,groupKeys[1: event_day] ,projectionnull ,predicatenull} - LogicalOlapScanOperator {table28673, selectedPartitionIdnull, selectedIndexId28674, outputColumns[1: event_day, 2: pv], predicatenull, prunedPartitionPredicates[], limit-1} plan 1: LogicalViewScanOperator {tableview1, outputColumns[4: event_day, 5: sum_pv]} | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1 row in set (0.01 sec)两个示例的输出一致该物化视图基于视图view1创建优化器为其生成了plan 0视图内联展开后的聚合 OLAP 扫描与plan 1直接扫描视图两套候选逻辑计划。补充说明该函数同时兼容简单的mv_name与db.mv_name全限定名写法FE 单测 ConstantExpressionTest.java 中即覆盖了inspect_mv_plan(mv1, true)、inspect_mv_plan(mv1, false)、inspect_mv_plan(mv1)三种调用形式并断言输出中包含LogicalOlapScanOperator {table关键字同时验证了基于视图创建的物化视图mv_from_view_1会输出多段plan。底层实现调用链与权限校验inspect_mv_plan的完整执行路径位于 MetaFunctions.java核心流程如下解析表名通过TableName.fromString(mvName.getVarchar())解析传入的物化视图名称查找并鉴权调用inspectTable(tableName)见 MetaFunctions.java从 FE 的 LocalMetastore 中获取 Database 与 Table并通过Authorizer.checkAnyActionOnTable校验当前用户对该表是否具备任意操作权限库不存在、表不存在或无权限都会抛出语义异常类型校验通过table.isMaterializedView()确认目标确实是物化视图否则抛出... is not materialized view语义异常获取计划上下文临时将会话变量enable_materialized_view_plan_cache设置为use_cache参数值调用CachingMvPlanContextBuilder.getInstance().getPlanContext(sessionVariable, mv)获取ListMvPlanContext随后恢复会话变量的原值格式化输出遍历所有MvPlanContext对非空项通过context.getLogicalPlan().debugString()得到逻辑计划的可读字符串拼装为plan %d: \n%s\n格式返回空项输出plan %d: null。从源码结构可以推断该函数本质上是复用了物化视图查询改写MV rewrite所使用的同一套计划构建与缓存设施——即inspect_mv_plan输出的计划正是查询改写阶段实际用于匹配候选物化视图的计划。因此它对于理解“为什么这条查询没被改写”具有直接的诊断价值。use_cache 参数与物化视图计划缓存use_cache参数控制是否从物化视图计划缓存中读取逻辑计划其底层行为由 CachingMvPlanContextBuilder.java 决定当use_cache TRUE默认走getOrLoadPlanContext路径从基于 Caffeine 的AsyncLoadingCache中读取缓存未命中时触发异步加载并受超时时间约束当use_cache FALSE走loadMvPlanContext路径跳过缓存、直接重新构建物化视图的逻辑计划适合验证缓存是否因元数据过期而失真。相关会话变量与 FE 配置名称位置默认值作用enable_materialized_view_plan_cache会话变量SessionVariable.javatrue是否启用物化视图计划缓存inspect_mv_plan的use_cache参数会临时覆盖它mv_plan_cache_max_sizeFE 静态配置Config.java1000物化视图计划缓存的条目上限mv_global_context_cache_max_sizeFE 静态配置Config.java5000每个物化视图级别上下文缓存的条目上限new_planner_optimize_timeout会话变量—获取计划缓存时的超时时间超时后返回null并记录告警日志缓存实现细节上CachingMvPlanContextBuilder使用独立的mv-plan-cache-%d线程池执行异步加载缓存的 value 为ListMvPlanContext因为基于视图的物化视图可能有多个候选计划。特别地缓存在写入前会通过removeHeavyObjectsFromTable将 Iceberg / Delta Lake 等外表替换为轻量级包装对象避免大对象长期驻留内存。物化视图每次元数据变化如 DDL、刷新都会触发evictMaterializedViewCache使缓存失效保证计划不因陈旧元数据而失真。与相关元数据函数的配合使用inspect_mv_plan常与同目录下的其他 meta function 组合使用形成完整的物化视图诊断链路均位于 docs/en/sql-reference/sql-functions/meta-functionsinspect_mv_meta查看物化视图的元数据信息如是否为物化视图、表结构等inspect_related_mv查看与某张基表相关的物化视图列表inspect_mv_refresh_info查看物化视图的刷新配置与状态。例如先用inspect_related_mv(mv_base_table)确认候选物化视图集合再用inspect_mv_plan检查候选视图的逻辑计划是否满足改写条件即可快速定位改写未命中的原因。小结inspect_mv_plan(mv_name[, use_cache])以 VARCHAR 返回物化视图的逻辑计划字符串默认走计划缓存输出中的LogicalAggregation、LogicalOlapScanOperator、LogicalViewScanOperator等算子字段完整刻画了物化视图在优化器中的形态可用于改写问题诊断底层实现复用了 MV 查询改写同一套计划构建与 Caffeine 缓存设施并受enable_materialized_view_plan_cache会话变量、mv_plan_cache_max_size等配置控制对于基于视图创建的物化视图函数会一次性返回多个候选计划便于理解“内联 / 不内联视图”两种改写路径。【免费下载链接】starrocksThe worlds fastest open query engine for sub-second analytics both on and off the data lakehouse. With the flexibility to support nearly any scenario, StarRocks provides best-in-class performance for multi-dimensional analytics, real-time analytics, and ad-hoc queries. A Linux Foundation project.项目地址: https://gitcode.com/GitHub_Trending/st/starrocks创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考