通过物化视图提升超大规模数据执行性能

更新时间:
复制为 MD 格式

在超大规模数据场景下,即时 SQL 分析可能面临执行超时、结果不精确等问题。物化视图通过对 SQL 子语句进行增量预计算并持久化中间结果,在后续查询时自动利用已计算数据并透明改写 SQL,将仪表盘等报表场景的查询耗时从分钟级降低至秒级。

选择加速策略

日志服务支持通过 SQL 对数据进行即时分析,每次 SQL 执行都对选定时间范围内的全量数据进行计算。在大规模数据量下,可通过以下方式提升分析性能:

加速方式

原理

适用场景

限制

高性能完全精确查询与分析(SQL独享版)

增加计算资源,提升单次查询的并行度

数据量较大,但查询 SQL 变化频繁

数据规模仍有上限,超大规模下执行时间较长

物化视图(本文)

对固定 SQL 的子语句进行增量预计算,查询时自动改写为读取预计算结果

SQL 相对固定的报表、仪表盘场景,数据规模超大

仅支持标准型 LogStore,每个 Project 最多 100 个物化视图

工作原理

  • 原始日志库:原始日志数据的 LogStore。物化视图不会对原始日志库产生任何影响。

  • 物化库:创建物化视图后,系统自动创建对应的物化库,用于存储预计算结果数据。

    物化按照写入数据流式处理。即使原始数据在日志时间上存在乱序,定时物化的结果也不会重复或遗漏。
  • 后台定时计算:系统自动从输入的 SQL 中提取需要物化的模式,定时对原始 LogStore 的数据计算中间结果。创建物化视图时只需提供目标 SQL,无需手动设计物化逻辑。

  • 透明改写:执行 SQL 查询时,日志服务的执行引擎自动分析 SQL 结构,匹配已有的物化视图并改写查询。查询仍然直接面向原始 LogStore,无需修改 SQL 语句或指定物化视图。

  • 自动合并保证数据完整性:对于已物化的数据范围,引擎直接从物化视图中读取结果;对于尚未物化的最新数据,从原始日志库实时读取并计算。两部分结果自动合并,确保返回完整且最新的查询结果。

image.png

说明

透明改写是物化视图的核心机制。与其他系统需要手动查询物化结果表不同,日志服务自动完成 SQL 匹配、改写和结果合并的全过程,无需修改任何现有查询语句。创建物化视图后,由于系统需要异步执行历史区间(起始时间至当前时间)的预计算任务,加速效果不会立即显现。根据数据量级和计算复杂度,该构建过程通常耗时 1 至 12 小时。预计算覆盖查询时间范围后,加速才可正式生效。

适用范围

  • 仅支持日志库标准型 LogStore,不支持查询型 LogStore、时序库 MetricStore、数据视图 StoreView 等。

  • 单个 Project 下创建的物化视图数量不能超过 100 个。

  • 支持通过控制台和 API 两种方式创建和管理物化视图。

权限要求

阿里云账号默认拥有所有权限,无需额外授权。RAM 用户需配置如下权限:

物化视图所需权限

向阿里云账号管理员申请日志服务的系统权限策略 AliyunLogFullAccess,或参考下表通过创建自定义权限策略实现精细化权限管理。

操作

权限 Action

创建物化视图

log:CreateMaterializedView

更新物化视图

log:UpdateMaterializedView

获取指定物化视图详情

log:GetMaterializedView

删除物化视图

log:DeleteMaterializedView

获取物化视图列表

log:ListMaterializedViews

使用物化视图

通过查询分析页面创建

在查询分析页面执行 SQL 后,可以直接基于当前查询创建物化视图。

  1. 登录日志服务控制台

  2. 单击Project列表中的目标 Project,单击目标 LogStore(标准型)。

  3. 在查询分析页面,输入需要加速的 SQL 语句,单击查询 / 分析

  4. 在查询结果的统计图表区域,单击创建物化视图

  5. 在创建物化视图向导中完成配置。SQL 代码会自动填入当前查询的 SQL 语句,其他配置参数说明与通过物化视图面板创建时相同。

通过物化视图面板创建与管理

创建物化视图

  1. 登录日志服务控制台

  2. 单击Project列表中的目标 Project。

  3. 单击左侧导航栏的物化视图图标。

  4. 单击物化视图面板的立即创建

  5. 按照创建物化视图向导,完成以下配置。

    1. 来源库:配置物化视图的数据来源。

      参数

      说明

      项目 Project

      自动填充为当前 Project,不可修改。

      源库类型

      选择Logstore。目前仅支持标准型 LogStore。

      日志库

      从下拉列表中选择要创建物化视图的目标 LogStore。

      配置完成后,单击下一步

    2. 物化视图配置:配置物化视图的名称和 SQL 等参数。

      参数

      说明

      物化视图名称

      输入物化视图的名称。系统会自动添加 mv_ 前缀,无需手动添加。

      SQL 代码

      输入需要通过物化加速的 SQL 语句。编辑器支持语法高亮和自动补全。输入 SQL 后,可以单击预览验证执行结果。

      说明

      SQL 中使用的列名必须已建立索引,否则预览时会报错。

      起始时间

      选择开始物化的时间点。该时间点是原始数据的写入时间,系统只物化该时间点之后的数据。

      视图更新间隔

      配置物化视图定时执行计算的时间周期,单位为分钟。间隔越短,物化结果越接近实时,但计算成本相应增加。

  6. 配置完成后,单击保存

    创建成功后,系统自动跳转至物化视图查询页面。

    说明

    物化视图的数据保存时间与关联的原始 LogStore 保持一致。单个 Project 下创建的物化视图数量不能超过 100 个。

查看和管理物化视图

创建物化视图后,可以在控制台查看和管理物化视图。

  • 查看物化视图列表

    单击目标 Project 左侧导航栏的物化视图图标,通过弹出的侧面板查看当前 Project 下的所有物化视图。

  • 查看物化视图详情

    单击物化视图列表中的目标物化视图名称,进入物化视图详情页。详情页展示以下配置信息:

    • 物化视图名称:物化视图的完整名称(含 mv_ 前缀)。

    • 起始时间:开始物化的时间点。

    • 视图更新间隔:定时执行物化计算的时间周期。

    • 数据保存时间:与原始 LogStore 的数据保存时间一致。

    • SQL代码:物化视图对应的 SQL 语句。

  • 删除物化视图

    在物化视图详情页,单击删除,然后单击确认对话框的确认

    警告

    物化视图删除后不可恢复,对应的物化库也会被删除。

仪表盘查询加速

如果仪表盘中存在查询延迟较高的图表,可以为其创建物化视图进行查询加速。具体操作,请参见仪表盘查询加速

通过 SDK 创建与管理

也可以通过 SDK 以编程方式创建和管理物化视图。以下以 Java 语言为例。

  1. 导入日志服务 Java SDK。

    <dependency>
        <groupId>com.aliyun.openservices</groupId>
        <artifactId>aliyun-log</artifactId>
        <version>0.6.138</version>
    </dependency>
  2. 以下示例包含物化视图的创建、列表获取、详情获取和删除操作,按需修改后执行。

    • 代码中参数获取方式参考如下:

      • accessKey 与 accessId 获取参考创建AccessKey

      • host 获取方式:

        1. 登录日志服务控制台,单击 Project 列表中的目标 Project。

        2. 单击 Project 名称右侧的image进入项目概览页面,从访问域名复制公网域名。

      import com.aliyun.openservices.log.Client;
      import com.aliyun.openservices.log.exception.LogException;
      import com.aliyun.openservices.log.request.CreateMaterializedViewRequest;
      import com.aliyun.openservices.log.request.ListMaterializedViewsRequest;
      import com.aliyun.openservices.log.response.GetMaterializedViewResponse;
      import com.aliyun.openservices.log.response.ListMaterializedViewsResponse;
      
      import java.text.SimpleDateFormat;
      import java.util.concurrent.TimeUnit;
      
      public class MvDemo
      {
          static String accessId = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID");
          static String accessKey = System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET");
          /**
           * 日志服务的服务接入点。此处以杭州为例,其它地域请根据实际情况填写。
           */
          static String host = "cn-hangzhou.log.aliyuncs.com";
          /**
           * 创建日志服务Client。
           */
          static Client client = new Client(host, accessId, accessKey);
          /**
           * Project名称。
           */
          static String projectName = "xxx";
          /**
           * LogStore名称。
           */
          static String logstoreName = "xxx";
      
          public static void main(String[] args) throws Exception {
              String materializedViewName = "test_mv";
      
              createMv(materializedViewName);//创建指定名称的物化视图
      
              listMv();//获取当前project下的物化视图列表
      
              getMv(materializedViewName);//获取当前物化视图信息
      
              // deleteMv(materializedViewName); //删除物化视图
          }
      
          static int dateStrToSecond(String dateStr) throws Exception {
              SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
              return (int)TimeUnit.MILLISECONDS.toSeconds(simpleDateFormat.parse(dateStr).getTime());
          }
      
          static void createMv(String materializedViewName) throws Exception {
              String originalSql = "* | select count(l1) as cnt, l2 from stability group by l2"; // 请修改为需要通过物化加速的SQL
              int aggInternalMins = 60; // 定时执行物化的时间周期,单位是分钟。
              int startTime = dateStrToSecond("2025-07-30 00:00:00"); // 开始物化的时间点:是原始数据的时间点(数据的写入时间)。限制只物化这个时间点之后的原始数据。
              int ttl = 0; // 物化库的TTL,设为0表示和原始LogStoreTTL保持一致,物化库的TTL不能小于原始库的TTL。
              //单个project下创建的物化视图数目不能超过 100个
              CreateMaterializedViewRequest request = new CreateMaterializedViewRequest(projectName, materializedViewName, logstoreName, originalSql, aggInternalMins, startTime, ttl);
              client.createMaterializedView(request);
              System.out.println("create materialized view " + materializedViewName);
          }
      
          static void listMv() throws LogException
          {
              ListMaterializedViewsRequest request = new ListMaterializedViewsRequest(projectName, "", 0, 10);//0,10为分页查询参数。
              ListMaterializedViewsResponse response = client.listMaterializedViews(request);
              System.out.println("total materialized view count: " + response.getTotal());
              for (String materializedView : response.getMaterializedViews()) {
                  System.out.println(materializedView);
              }
          }
      
          static void getMv(String materializedViewName) throws Exception
          {
              GetMaterializedViewResponse response = client.getMaterializedView(projectName, materializedViewName);
              System.out.println("get materialized view detail, name: " + materializedViewName);
              System.out.println("originalSql: " + response.getOriginalSql());
              System.out.println("startTime: " + response.getStartTime());
              System.out.println("ttl: " + response.getTtl());
          }
      
          static void deleteMv(String materializedViewName ) throws LogException {
              client.deleteMaterializedView(projectName, materializedViewName);
              System.out.println("delete materialized view " + materializedViewName);
          }
      
      }

支持的语法

  • 支持所有的标量函数和表达式。

  • 支持 WHERE 条件、GROUP BY、LIMIT、TOP-N 等语句。

  • 支持常见的聚合函数,详细列表如下:

支持的聚合函数

语法

聚合函数

count(*)

count(1)

count(x)

count_if(boolean expression)

max(x)

max(xn)

min(x)

min(xn)

sum(x)

arbitrary(x)

估算函数

approx_distinct(x)

approx_distinct(xe)

approx_percentile(xpercentage)

计费说明

物化视图的计费基于写入物化库的数据量,取决于 SQL 定时计算的结果数据量,通常远小于原始 LogStore 的数据量。具体按照标准型 LogStore 的按写入数据量计费

说明

降低物化成本的方式:避免在 GROUP BY 中使用高基数字段(如时间戳、用户 ID),选择与业务刷新频率匹配的物化更新间隔。