Starrocks 物化视图的实现以及在刷新期间能否读数据

背景

本司在用Starrocks做一些业务上的分析的时候,用到了物化视图,并且在高QPS的情况下,RT也没有很大的波动,所以在此研究一下Starrock的实现,以及在刷新的时候是不是原子性的

本文基于Starrocks 3.3.5

结论

Starrocks的物化视图的更新是通过Insert Overwrite的方式实现的,在执行该SQL期间,会新建临时分区并进行替换,最后在替换分区的时候,会进行表加锁操作,所以说物化视图不存在读不到数据的情况。

分析

这里我们只关心主流程,其他的细节直接跳过

物化视图的创建

直接到 Starrocks.g4

复制代码
createMaterializedViewStatement

这里会用 AstBuilder.visitCreateMaterializedViewStatement 生成 CreateMaterializedViewStatementMaterializedViewAnalyzer.visitCreateMaterializedViewStatement 方法进行物化视图的解析,主要是解析里面的SQL,并生成物理计划,

之后再走到StmtExecutor.handleDdlStmt 方法:

复制代码
    private void handleDdlStmt() throws DdlException {
        try {
            ShowResultSet resultSet = DDLStmtExecutor.execute(parsedStmt, context);
            if (resultSet == null) {
                context.getState().setOk();
            } else {

最后会走到LoaclMetaStore.createMaterializedView方法:

复制代码
 @Override
    public void createMaterializedView(CreateMaterializedViewStatement stmt)
            throws DdlException {
        // check mv exists,name must be different from view/mv/table which exists in metadata
        String mvName = stmt.getTableName().getTbl();
        String dbName = stmt.getTableName().getDb();
        。。。
        createTaskForMaterializedView(dbName, materializedView, optHints);

这个createTaskForMaterializedView方法

  • 有个Task task = TaskBuilder.buildMvTask(materializedView, dbName);方法:

    public static Task buildMvTask(MaterializedView materializedView, String dbName) {
    Task task = new Task(getMvTaskName(materializedView.getId()));
    ...
    task.setDefinition(materializedView.getTaskDefinition());
    task.setPostRun(getAnalyzeMVStmt(materializedView.getName()));
    task.setExpireTime(0L);
    if (ConnectContext.get() != null) {
    task.setCreateUser(ConnectContext.get().getCurrentUserIdentity().getUser());
    task.setUserIdentity(ConnectContext.get().getCurrentUserIdentity());
    }
    handleSpecialTaskProperties(task);
    return task;
    }

其中 materializedView.getTaskDefinition 代码如下:

复制代码
    public String getTaskDefinition() {
        return String.format("insert overwrite `%s` %s", getName(), getViewDefineSql());
    }

可以看到这里是insert overwrite的方式.

  • 与此同时,createTaskForMaterializedView还调用TaskManager.createTask方法用来周期性的调度任务

物化视图的执行

上面看到物化视图的执行是通过Insert overwrite的方式实现的,所以

直接找到Starrocks.g4:

复制代码
insertStatement

通过AstBuilder.visitInsertStatement解析,解析为InsertStmt,最后会转到StmtExecutor.handleDMLStmtWithProfile:

复制代码
handleDMLStmt
 ||
 \/
handleInsertOverwrite
 ||
 \/
InsertOverwriteJobMgr.executeJob
 ||
 \/
InsertOverwriteJobRunner.run()
 ||
 \/
InsertOverwriteJobRunner.doLoad()

InsertOverwriteJobRunner.doLoad() 方法如下:

复制代码
        Preconditions.checkState(job.getJobState() == InsertOverwriteJobState.OVERWRITE_RUNNING);
        createTempPartitions();
        prepareInsert();
        executeInsert();
        doCommit(false);
        transferTo(InsertOverwriteJobState.OVERWRITE_SUCCESS);
  • createTempPartitions(); 这个主要创建临时分区。

  • prepareInsert/executeInsert 这里主要是进行临时分区的数据写入

  • doCommit 这会进行分区的替换

    复制代码
         Locker locker = new Locker();
         if (!locker.lockDatabaseAndCheckExist(db, tableId, LockType.WRITE)) {
             throw new DmlException("insert overwrite commit failed because locking db:%s failed", dbId);
         }
         ...
         targetTable.replacePartition(sourcePartitionNames.get(0), tmpPartitionNames.get(0));
         ...
         } finally {
             locker.unLockDatabase(db, tableId, LockType.WRITE);
         }

    不同于之前的数据写入操作,这里会进行锁表的操作,也就是在这期间读写是有互斥的,并且这里面分区(非分区表其实也是有单个分区的存在)的替换都是内存操作,所以会很快。

所以从实现来说,insert overwrite在执行阶段是互斥的,并且只有在元数据操纵期间才会加锁,数据写入阶段是不会加锁的,所以速度是很快的。

相关推荐
一定要AK7 小时前
Spring 入门核心笔记
java·笔记·spring
A__tao7 小时前
Elasticsearch Mapping 一键生成 Java 实体类(支持嵌套 + 自动过滤注释)
java·python·elasticsearch
KevinCyao8 小时前
java视频短信接口怎么调用?SpringBoot集成视频短信及回调处理Demo
java·spring boot·音视频
一江寒逸8 小时前
零基础从入门到精通MySQL(中篇):进阶篇——吃透多表查询、事务核心与高级特性,搞定复杂业务SQL
数据库·sql·mysql
2501_948114248 小时前
2026年大模型API聚合平台技术评测:企业级接入层的治理演进与星链4SAPI架构观察
大数据·人工智能·gpt·架构·claude
迷藏4948 小时前
**发散创新:基于Rust实现的开源合规权限管理框架设计与实践**在现代软件架构中,**权限控制(RBAC)** 已成为保障
java·开发语言·python·rust·开源
黎阳之光8 小时前
黎阳之光:视频孪生领跑者,铸就中国数字科技全球竞争力
大数据·人工智能·算法·安全·数字孪生
wuxinyan1239 小时前
Java面试题47:一文深入了解Nginx
java·nginx·面试题
新知图书9 小时前
搭建Spring Boot开发环境
java·spring boot·后端
冰河团队9 小时前
一个拉胯的分库分表方案有多绝望?整个部门都在救火!
java·高并发·分布式数据库·分库分表·高性能