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

相关推荐
向着光芒的女孩19 小时前
【IDEA】关不了的Proxy Authentication弹框探索过程
java·ide·intellij-idea
Filotimo_20 小时前
Spring Boot 整合 JdbcTemplate(持久层)
java·spring boot·后端
李慕婉学姐20 小时前
【开题答辩过程】以《“饭否”食材搭配指南小程序的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·spring·小程序
2501_9414043121 小时前
绿色科技与可持续发展:科技如何推动环境保护与资源管理
大数据·人工智能
abments21 小时前
pgsql timestamp without time zone > character varying解决方案
java
swanwei1 天前
量子科技对核心产业的颠覆性影响及落地时间表(全文2500字)
大数据·网络·人工智能·程序人生·量子计算
sanggou1 天前
大数据量查询处理方案 - 内存优化与高效展示
java
没有bug.的程序员1 天前
Java 字节码:看懂 JVM 的“机器语言“
java·jvm·python·spring·微服务
-大头.1 天前
深入理解 Java 内存区域与 JVM 运行机制
java·jvm
没有bug.的程序员1 天前
JVM 整体架构:一套虚拟机的心脏与血管
java·jvm·spring boot·spring cloud·架构