StarRocks CREATE VIEW 详解:逻辑视图创建、安全视图(SECURITY)与源码级实现原理
StarRocks CREATE VIEW 详解逻辑视图创建、安全视图SECURITY与源码级实现原理【免费下载链接】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/starrocksCREATE VIEW 是 StarRocks 中创建逻辑视图Logical View的核心 DDL 语句。它把一段查询固化为可复用的虚拟表不占用物理存储查询视图等价于执行其背后的子查询。本文以官方 SQL 参考文档为基础完整覆盖CREATE VIEW的语法、参数、安全视图SECURITY NONE/INVOKER自 v3.4.1 起支持、使用注意事项与实战示例并结合当前仓库 FE 源码解析、分析、授权、执行全链路与单元测试深入剖析视图的底层实现帮助读者在 StarRocks 中正确地创建、管理并安全地使用视图。一、什么是逻辑视图视图View又称逻辑视图Logical View是一种虚拟表它的数据并不真实存储而是由一条针对其他物理表或视图的查询语句派生而来。因此视图不占用任何物理存储不复制底层数据查询视图等价于执行构建该视图的查询语句作为子查询视图对使用者隐藏了底层表结构可以沉淀常用的复杂查询多表关联、聚合、窗口函数等为可复用对象同时是 StarRocks 实现行级/列级安全的重要手段。StarRocks 中的视图分为两类类型说明官方文档逻辑视图View本文主题无物理存储查询时动态展开本文同步物化视图与基表同步维护有物理存储Synchronous materialized views异步物化视图异步刷新可跨表、跨 catalogAsynchronous materialized views物化视图会物化存储查询结果以加速查询而逻辑视图仅做查询的封装两者定位不同创建与维护语法也完全不同。二、CREATE VIEW 完整语法CREATE [OR REPLACE] VIEW [IF NOT EXISTS] [database.]view_name ( column_name[ COMMENT column comment] [, column_name[ COMMENT column comment], ...] ) [COMMENT view comment] [SECURITY {NONE | INVOKER}] AS query_statement注意CREATE VIEW与CREATE MATERIALIZED VIEW语法并不相同前者创建逻辑视图后者创建物化视图。参数说明参数描述OR REPLACE替换已存在的同名视图。若目标视图不存在CREATE OR REPLACE VIEW直接创建新视图。IF NOT EXISTS若同名视图已存在则不执行创建不报错。注意IF NOT EXISTS与OR REPLACE不能同时出现解析器会直接报冲突错误见下文源码分析。database视图所在的数据库名称可省略省略时默认使用当前数据库。view_name视图名称命名需遵循 System limits 中的对象命名规范仅可由数字、字母、下划线组成以字母或下划线开头长度不超过 64 字符且区分大小写。column_name视图的列名列表。视图列的数量必须与query_statement查询输出列的数量一致若不显式指定列名则直接继承查询输出列的名称。COMMENT列的注释或视图本身的注释用于元数据管理与人可读描述。SECURITY指定视图被调用invocation时进行权限校验的安全上下文决定谁能查询该视图。合法取值NONE默认与INVOKER详见下文安全视图章节。query_statement构建视图的查询语句可以是 StarRocks 支持的任何查询语句包括多表 JOIN、聚合、窗口函数等。三、安全视图SECURITY NONE 与 SECURITY INVOKER从v3.4.1开始StarRocks 支持安全视图Secure View。安全视图解决的核心问题是能否限制对视图有 SELECT 权限、但对基表没有 SELECT 权限的用户查询该视图。SECURITY取值行为适用场景NONE默认用户只需对视图本身拥有 SELECT 权限即可查询视图不额外检查其对基表的权限。通过视图做行/列级权限收敛把 SELECT 权限授予视图而非底层表实现白名单列数据暴露。INVOKER用户必须同时对视图本身和视图引用的所有基表拥有 SELECT 权限才能查询视图。基表本身敏感如含手机号、身份证列禁止通过视图间接绕过基表权限管控。也就是说SECURITY INVOKER会阻止只对视图有权限、对底层基表无权限的用户利用视图越权读取数据。会话级默认值default_view_sql_security在 SQL 语句省略SECURITY子句时视图的安全特性由会话变量default_view_sql_security决定NONE默认值等价于显式声明SECURITY NONEINVOKER等价于显式声明SECURITY INVOKER。设置方式示例SET default_view_sql_security INVOKER;从源码看该逻辑在分析阶段完成。ViewAnalyzer.java 的visitCreateViewStatement中当语句未显式指定SECURITY时!stmt.isSecurityExplicit()会读取context.getSessionVariable().getDefaultViewSqlSecurity()回填安全特性if (!stmt.isSecurityExplicit()) { DefaultViewSqlSecurity defaultSecurity context.getSessionVariable().getDefaultViewSqlSecurity(); stmt.setSecurity(defaultSecurity DefaultViewSqlSecurity.INVOKER); }而DefaultViewSqlSecurity枚举定义于 SessionVariableConstants.java默认值为NONEpublic enum DefaultViewSqlSecurity { NONE, // 仅检查调用者对视图本身的权限映射 SECURITY NONE INVOKER; // 额外检查调用者对视图所引用基表的权限映射 SECURITY INVOKER public static DefaultViewSqlSecurity getDefault() { return NONE; } }优先级规则由单元测试 CreateViewTest.java 的testDefaultViewSqlSecurity与testDefaultViewSqlSecurityWithReplace完整覆盖语句中显式声明的SECURITY子句永远优先于会话默认值省略SECURITY子句时采用会话变量default_view_sql_security的值CREATE OR REPLACE VIEW在替换既有视图时同样遵循上述规则——会话默认值变化会改变被替换后视图的安全特性而显式SECURITY子句则固定其取值。安全视图的权限校验语义查询视图时StarRocks 的授权器Authorizer会根据视图的security标记决定校验范围。视图的安全标记存储在 FE 元数据对象 View.java 中private boolean security false默认即SECURITY NONE视图security falseSECURITY NONE查询仅校验用户对视图本身的 SELECT 权限视图security trueSECURITY INVOKER查询同时校验用户对视图及视图所引用基表的 SELECT 权限。四、使用注意事项查询一个视图需要拥有对该视图的 SELECT 权限若视图为SECURITY INVOKER安全视图还需要对其引用的全部基表拥有 SELECT 权限。如果构建视图的查询语句因基表发生Schema Change表结构变更而无法继续执行StarRocks 会在你查询该视图时返回错误——因此对视图所依赖的基表做结构变更前需要评估对既有视图的影响。视图不能基于**临时表Temporary Table**创建。该限制在分析器中有显式校验ViewAnalyzer中AnalyzerUtils.hasTemporaryTables检查命中时抛出SemanticException: View cant base on temporary table。视图的查询语句中禁止使用Time Travel时间旅行查询分析器通过AnalyzerUtils.prohibitTimeTravelQuery(..., create view)拦截。权限要求执行CREATE VIEW需要拥有目标数据库的CREATE VIEW 权限同时创建视图所用查询语句涉及的表要求执行者拥有相应查询权限。从源码看这两条权限检查在 AuthorizerStmtVisitor.java 的visitCreateViewStatement中依次完成先通过Authorizer.checkDbAction(catalog, dbName, PrivilegeType.CREATE_VIEW)校验数据库级CREATE_VIEW权限再通过check(statement.getQueryStatement(), context)校验查询语句涉及对象的权限。五、实战示例以下示例均以表example_table含列c1、k1、k2、k3、v1为基础。示例 1创建基础视图聚合查询在example_db中创建名为example_view的视图封装对example_table的聚合查询视图列名为k1, k2, k3, v1CREATE VIEW example_db.example_view (k1, k2, k3, v1) AS SELECT c1 as k1, k2, k3, SUM(v1) FROM example_table WHERE k1 20160112 GROUP BY k1,k2,k3;这里通过c1 AS k1将基表列c1重命名为视图列k1视图列的数量4 个与查询输出列的数量严格对应。示例 2带注释的视图为视图本身和每个视图列添加注释便于元数据管理CREATE VIEW example_db.example_view ( k1 COMMENT first key, k2 COMMENT second key, k3 COMMENT third key, v1 COMMENT first value ) COMMENT my first view AS SELECT c1 as k1, k2, k3, SUM(v1) FROM example_table WHERE k1 20160112 GROUP BY k1,k2,k3;注释会写入视图的元数据可以通过SHOW CREATE VIEW等语句查看。单元测试createViewWithComment也验证了视图定义中的注释如 SQL 行内注释-- This is a comment from user会被完整保留在视图定义中。示例 3创建安全视图SECURITY INVOKER在example_db中创建安全视图example_view要求查询者必须同时拥有基表example_table的 SELECT 权限CREATE VIEW example_db.example_view (k1, k2, k3, v1) COMMENT my secure view SECURITY INVOKER AS SELECT c1 as k1, k2, k3, SUM(v1) FROM example_table WHERE k1 20160112 GROUP BY k1,k2,k3;创建后仅对视图有 SELECT 权限、对example_table无 SELECT 权限的用户将无法查询该视图。示例 4幂等创建与替换-- 仅当视图不存在时创建 CREATE VIEW IF NOT EXISTS example_db.example_view AS SELECT k1, k2 FROM example_table; -- 视图已存在则原子替换不可与 IF NOT EXISTS 同时使用 CREATE OR REPLACE VIEW example_db.example_view AS SELECT k1, k2, k3 FROM example_table;六、视图的查看、修改与删除创建视图后可配合以下语句完成视图生命周期管理SHOW CREATE VIEW查看视图定义SHOW CREATE VIEW返回创建视图时的 CREATE VIEW 语句帮助理解视图定义并作为修改、重建的参考。需要拥有视图及其基表的 SELECT 权限自 v2.5.4 起也支持查询物化视图的创建语句。SHOW CREATE VIEW [db_name.]view_name输出结果包含View视图名、Create View视图的 CREATE 语句、character_set_client与collation_connection四个字段。完整说明见 SHOW CREATE VIEW。ALTER VIEW修改视图定义视图是逻辑对象修改视图定义等价于修改其query_statementALTER VIEW [db_name.]view_name (column1[ COMMENT col comment][, column2, ...]) AS query_stmt例如ALTER VIEW example_db.example_view ( c1 COMMENT column 1, c2 COMMENT column 2, c3 COMMENT column 3 ) AS SELECT k1, k2, SUM(v1) FROM example_table GROUP BY k1, k2;完整说明见 ALTER VIEW。DROP VIEW删除视图DROP VIEW [IF EXISTS] [db_name.]view_name示例DROP VIEW IF EXISTS example_db.example_view;IF EXISTS可避免视图不存在时抛错。完整说明见 DROP VIEW。七、源码级原理一条 CREATE VIEW 语句的完整旅程结合 FE 源码CREATE VIEW的执行链路可分为五个阶段1. 语法解析ParserAstBuilder.java 的visitCreateViewStatement将 SQL 文本解析为 AST 节点 CreateViewStmt.java解析IF NOT EXISTS与OR REPLACE标志且两者互斥——同时出现时直接抛出ParsingExceptionconflictedOptions(if not exists, or replace)解析显式的SECURITY NONE / SECURITY INVOKER记录securityExplicit是否显式指定解析视图注释、列名与列注释ColWithComment列表以及查询语句并记录查询语句在原始 SQL 中的起止位置queryStartIndex/queryStopIndex供后续截取原始视图定义文本使用。2. 语义分析AnalyzerViewAnalyzer.java 的visitCreateViewStatement负责归一化表引用、校验视图名称合法性FeNameFormat.checkTableName处理上文所述的SECURITY会话默认值回填逻辑校验视图不允许基于临时表、不允许时间旅行查询通过analyzeViewColumns推导视图列若用户未显式指定列名则从查询输出字段RelationFields自动生成视图列类型取自字段类型以保证 UNION 等场景下类型正确若用户指定了列名/注释则校验列数量必须与查询输出列数量一致否则报错ERR_VIEW_WRONG_LIST并检测重复列名生成两段视图定义文本并存储inlineViewDef重写后的规范化视图 SQLAstToSQLBuilder.toSQLWithCredential与originalViewDefineSql从原始语句中截取的用户书写原文。3. 权限校验AuthorizerAuthorizerStmtVisitor.java 校验执行者拥有目标库的CREATE_VIEW权限并校验查询语句涉及对象的权限见第四节。4. 执行与元数据落库ExecutorDDLStmtExecutor.java 的visitCreateViewStatement将执行委托给元数据管理器GlobalStateMgr.getCurrentState().getMetadataMgr().createView(context, stmt);对于内部 Catalog视图定义、列信息、注释与安全标记写入 FE 元数据对应View表对象 View.java对于外部 Catalog视图定义会转换为ConnectorViewDefinition写入对应连接器如 Iceberg。另外CreateViewStmt中的properties仅允许为Iceberg 视图设置属性对其他 Catalog 会抛出SemanticException。5. 查询时展开Runtime视图在查询时被当作内联子查询展开StarRocks 读取视图的inlineViewDef将其替换进查询计划再对底层基表执行真实的扫描与计算。这正是查询视图等价于子查询这一特性的底层机制。八、测试验证仓库中的单元测试 CreateViewTest.java 覆盖了本文涉及的关键行为可作为复现与验证的参考createViewWithComment验证视图定义含注释可被SHOW CREATE VIEW完整还原testDefaultViewSqlSecurity验证default_view_sql_security会话变量的NONE/INVOKER默认值行为以及显式SECURITY子句对默认值的覆盖优先级testDefaultViewSqlSecurityWithReplace验证CREATE OR REPLACE场景下会话默认值与显式SECURITY的交互。九、总结CREATE VIEW是 StarRocks 中创建逻辑视图的标准入口语法简洁但功能完整支持OR REPLACE原子替换、IF NOT EXISTS幂等创建、列注释与视图注释、任意查询语句封装以及自 v3.4.1 起的安全视图能力SECURITY NONE/INVOKER受会话变量default_view_sql_security控制。理解其查询时展开为子查询的物理本质掌握安全视图的权限语义并配合SHOW CREATE VIEW、ALTER VIEW、DROP VIEW完成全生命周期管理即可在 StarRocks 中安全、高效地复用查询逻辑并实施细粒度的数据权限管控。若需要真正的查询加速能力存储结果、自动刷新请参考 Synchronous materialized views 与 Asynchronous materialized views。【免费下载链接】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),仅供参考