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在执行阶段是互斥的,并且只有在元数据操纵期间才会加锁,数据写入阶段是不会加锁的,所以速度是很快的。

相关推荐
tachibana28 分钟前
hot100 排序链表(148)
java·数据结构·算法·leetcode·链表
wear工程师15 分钟前
synchronized 锁升级:多数人还在背 JDK8 的答案,偏向锁早在 JDK18 就没了
java·面试
灯澜忆梦16 分钟前
【MySQL1】| DDL 数据定义语言
数据库·sql·mysql
2601_9499369618 分钟前
2026财务分析师岗位,如何提升工作能力
大数据
荣码21 分钟前
LangGraph多步工作流:Agent不够用的时候,我踩了4个坑
java·python
是小李呀26 分钟前
Java集合扩容机制解析:ArrayList与HashMap底层原理及性能差异
java
SimonKing26 分钟前
FreeLLMAPI:24 家厂商、128 个模型、1 个 Key智能切换所有可用的模型
java·后端·程序员
阿pin26 分钟前
Java随笔-JVM内存模型
java·开发语言·jvm·内存模型
媒介发稿小能手43 分钟前
权威+垂直+全域媒体资源:选对GEO发稿平台,抢占AI搜索高地
大数据·人工智能·媒体