全部产品
Search
文档中心

云原生大数据计算服务 MaxCompute:CREATE MATERIALIZED VIEW

更新时间:Dec 19, 2024

基于满足物化视图场景的数据创建物化视图,支持分区和聚簇场景。

背景信息

视图是一种虚拟表,任何对视图的查询,都会转换为视图SQL语句的查询。而物化视图是一种特殊的物理表,物化视图会存储实际的数据,占用存储资源。更多物化视图计费信息,请参见计费规则

物化视图适用于如下场景:

  • 模式固定、且执行频次高的查询。

  • 查询包含非常耗时的操作,比如聚合、连接操作等。

  • 查询仅涉及表中的很小部分数据。

物化视图与传统查询的对比如下。

对比项

传统查询方式

物化视图查询方式

查询语句

直接使用SQL语句查询数据。

SELECT empid,deptname  
FROM emps JOIN depts 
ON emps.deptno=depts.deptno 
WHERE hire_date >= '2018-01-01';

您需要创建物化视图,然后基于物化视图查询数据。

创建物化视图语句如下:

CREATE MATERIALIZED VIEW mv 
AS SELECT empid,deptname, hire_date  
FROM emps JOIN depts 
ON emps.deptno=depts.deptno 
WHERE hire_date >= '2016-01-01';

基于创建的物化视图查询数据:

SELECT empid, deptname FROM mv 
WHERE hire_date >= '2018-01-01';

如果物化视图开启了查询改写功能,使用如下SQL语句查询数据时会直接从物化视图中查询数据:

SELECT empid,deptname 
FROM emps JOIN depts 
ON emps.deptno=depts.deptno 
WHERE hire_date >= '2018-01-01';
--相当于如下语句。
SELECT empid, deptname FROM mv 
WHERE hire_date >= '2018-01-01';

查询特点

查询涉及读表、JOIN、过滤(WHERE)操作。当源表数据量很大时,查询速度会很慢。操作复杂度较高,运行效率低。

查询涉及读表、过滤操作。不涉及JOIN操作。MaxCompute会自动匹配到最优物化视图,并直接从物化视图中读取数据,从而大大提高查询效率。

物化视图相关操作命令如下。

类型

功能

角色

操作入口

创建物化视图(支持分区和聚簇)

基于查询语句创建物化视图。

具备项目创建表权限(CreateTable)的用户。

本文中的命令您可以在如下工具平台执行:

更新物化视图

更新已创建的物化视图。

具备修改表权限(Alter)的用户。

修改物化视图的生命周期

修改已创建的物化视图的生命周期。

具备修改表权限(Alter)的用户。

开启或禁用物化视图的生命周期

开启或禁用已创建的物化视图的生命周期。

具备修改表权限(Alter)的用户。

查询物化视图信息

查询物化视图的基本信息。

具备读取表元信息权限(Describe)的用户。

查询物化视图状态

查看物化视图有效或无效。

具备读取表元信息权限(Describe)的用户。

删除物化视图

删除已创建的物化视图。

具备删除表权限(Drop)的用户。

删除物化视图分区

删除已创建的物化视图的分区。

具备删除表权限(Drop)的用户。

物化视图查询穿透

当查询的分区数据不存在时,需要自动实现到原始分区表查询数据。

具备项目写权限(Write)及创建表权限(CreateTable)的用户。

物化视图查询改写

对查询语句进行查询改写。

具备项目写权限(Write)及创建表权限(CreateTable)的用户。

物化视图定时更新

定时更新已创建物化视图的数据。

具备修改表权限(Alter)的用户。

计费规则

物化视图费用包含如下两部分:

  • 存储费用

    物化视图会占用物理存储空间,会产生存储费用,按量计费。更多计费信息,请参见存储费用(按量计费)

  • 计算费用

    创建、更新、查询物化视图及查询改写(物化视图有效)过程中涉及到查询数据,会消耗计算资源产生计算费用。

    • 当MaxCompute项目的规格类型为包年包月时,不单独收费。

    • 当MaxCompute项目的规格类型为按量计费时,按照SQL复杂度及输入数据量计算费用。更多计费信息,请参见SQL标准计费。您需要注意如下信息:

      • 更新物化视图执行的SQL与创建物化视图执行的SQL相同,如果该物化视图所在项目绑定的是预付费(包年包月)计算资源组,那么会使用已经购买的预付费资源,不会有额外费用;如果绑定的是后付费资源组,费用取决于执行SQL时输入的数据量和复杂度。同时刷新物化视图后会按照实际存储大小收取存储费用。

      • 当物化视图处于生效状态时查询改写会从物化视图中读取数据,查询语句的输入数据量(从物化视图读取部分)与物化视图相关,与物化视图源表无关。当物化视图处于失效状态时不支持查询改写,查询语句会直接查询源表,查询语句的输入数据量与源表相关。更多查询物化视图状态信息,请参见查询物化视图状态

      • 由于多表关联生成物化视图会产生数据膨胀等原因,从物化视图读取的数据量不一定绝对小于源表,MaxCompute不能保证读取物化视图一定比读取源表节省费用。

使用限制

物化视图的使用限制如下:

  • 不支持窗口函数。

  • 不支持UDTF函数。

  • 默认不支持非确定性函数(例如UDF、UDAF等)。当您的业务场景必须要使用非确定性函数时,请在Session级别设置属性set odps.sql.materialized.view.support.nondeterministic.function=true;

注意事项

  • 当查询语句执行失败时,物化视图也会创建失败。

  • 物化视图分区列必须来源于某张源表,其顺序和列数目必须和源表一样,列名称可以不一样。

  • 列注释需要指定所有列,包含分区列。如果只指定部分列,会报错。

  • 可以同时指定分区和聚簇,此时每个分区中的数据都有指定的聚簇属性。

  • 当查询语句中包含不支持的算子时会报错。物化视图支持的算子列表,请参见基于物化视图执行查询改写操作

  • MaxCompute默认不支持使用非确定性函数(例如UDF、UDAF等)创建物化视图。当您的业务场景必须要使用非确定性函数时,请在Session级别设置属性set odps.sql.materialized.view.support.nondeterministic.function=true;

  • 物化视图支持生成空分区,原始表分区为空的时候,刷新物化视图,自动生成空分区。

命令格式

CREATE MATERIALIZED VIEW [IF NOT EXISTS][project_name.]<mv_name>
[LIFECYCLE <days>]    --指定生命周期
[BUILD DEFERRED]    -- 指定是在创建时只生成表结构,不生成数据
[(<col_name> [COMMENT <col_comment>],...)]    --列注释
[DISABLE REWRITE]    --指定是否用于改写
[COMMENT 'table comment']    --表注释
[PARTITIONED ON/BY (<col_name> [, <col_name>, ...])    --创建物化视图表为分区表
[CLUSTERED BY|RANGE CLUSTERED BY (<col_name> [, <col_name>, ...])
     [SORTED BY (<col_name> [ASC | DESC] [, <col_name> [ASC | DESC] ...])]
                 INTO <number_of_buckets> BUCKETS]    --用于创建聚簇表时设置表的Shuffle和Sort属性
[TBLPROPERTIES("compressionstrategy"="normal/high/extreme",    --指定表数据存储压缩策略
                "enable_auto_substitute"="true",    --指定当分区不存在时是否转化视图来查询
                "enable_auto_refresh"="true",    --指定是否开启自动刷新
                "refresh_interval_minutes"="120",    --指定刷新时间间隔
                "only_refresh_max_pt"="true"    --针对分区物化视图,只自动刷新源表最新分区
                )]
AS <select_statement>;

参数说明

参数

是否必填

参数说明

IF NOT EXISTS

如果没有指定IF NOT EXISTS且物化视图已经存在会返回报错。

project_name

物化视图所属目标MaxCompute项目名称。不填写时表示当前所在MaxCompute项目。您可以登录MaxCompute控制台,左上角切换地域后,即可在项目管理页面查看到具体的MaxCompute项目名称。

mv_name

新建物化视图的名称。

days

指定物化视图的生命周期,单位为天。取值范围为1~37231。

BUILD DEFERRED

如果加上这个关键字代表创建物化视图时,只生成表结构,不刷新数据。

col_name

指定物化视图的列名称。

col_comment

指定物化视图的列的注释。

DISABLE REWRITE

设置禁止通过物化视图执行查询改写操作。不指定时表示允许通过物化视图执行查询改写操作,您可以执行ALTER MATERIALIZED VIEW [project_name.]<mv_name> DISABLE REWRITE;命令禁止通过物化视图执行查询改写操作。同理您可以执行ALTER MATERIALIZED VIEW [project_name.]<mv_name> ENABLE REWRITE;命令允许通过物化视图执行查询改写操作。

PARTITIONED ON

指定物化视图分区字段,表示创建的物化视图表为分区表。

CLUSTERED BY|RANGE CLUSTERED BY

用于创建聚簇表时设置表的Shuffle属性。

SORTED BY

用于创建聚簇表时设置表的Sort属性。

number_of_buckets

用于创建聚簇表时设置表分桶数。

TBLPROPERTIES

  • compressionstrategy指定表数据的存储压缩策略,可以选normal、high或extreme。enable_auto_substitute指定当分区不存在时是否自动穿透到原始分区表去查询数据,详细信息请参见物化视图查询改写

  • enable_auto_refresh:可选,当需要自动刷新数据时需要设置为true

  • refresh_interval_minutes:条件可选,当enable_auto_refreshtrue时,需要配置刷新间隔时间,单位为分钟。

  • only_refresh_max_pt:可选,只适用于带分区的物化视图,但设置为true时,只会刷新源表最新分区。

select_statement

查询语句,详细格式请参见SELECT语法

使用示例

创建物化视图

  1. 创建mf_tmf_t1两张表并插入数据。

    CREATE TABLE IF NOT EXISTS mf_t( 
         id     bigint, 
         value   bigint, 
         name   string) 
    PARTITIONED BY (ds STRING); 
    
    ALTER TABLE mf_t ADD PARTITION (ds='1'); 
    INSERT INTO mf_t PARTITION (ds='1') VALUES (1,10,'kyle'),(2,20,'xia'); 
    SELECT * FROM mf_t WHERE ds ='1'; 
    -- 返回结果如下。
    +------------+------------+------------+------------+
    | id         | value      | name       | ds         |
    +------------+------------+------------+------------+
    | 1          | 10         | kyle       | 1          |
    | 2          | 20         | xia        | 1          |
    +------------+------------+------------+------------+
    
    CREATE TABLE IF NOT EXISTS mf_t1( 
         id     bigint, 
         value   bigint, 
         name   string) 
    PARTITIONED BY (ds STRING); 
    
    ALTER TABLE mf_t1 ADD PARTITION (ds='1'); 
    INSERT INTO mf_t1 PARTITION (ds='1') VALUES (1,10,'kyle'),(3,20,'john'); 
    SELECT * FROM mf_t1 WHERE ds ='1';
    -- 返回结果如下。
    +------------+------------+------------+------------+
    | id         | value      | name       | ds         |
    +------------+------------+------------+------------+
    | 1          | 10         | kyle       | 1          |
    | 3          | 20         | john       | 1          |
    +------------+------------+------------+------------+
  2. 创建物化视图。

    • 示例1:创建以ds为分区列的物化视图。

      CREATE MATERIALIZED VIEW mf_mv LIFECYCLE 7
      (
        key comment 'unique id',
        value comment 'input value',
        ds comment 'partitiion'
        )
      PARTITIONED ON (ds)
      AS SELECT t1.id AS key, t1.value AS value, t1.ds AS ds
           FROM mf_t AS t1 JOIN mf_t1 AS t2
             ON t1.id = t2.id AND t1.ds=t2.ds AND t1.ds='1';
      --查询物化视图
      SELECT * FROM mf_mv WHERE ds =1;
      +------------+------------+------------+
      | key        | value      | ds         |
      +------------+------------+------------+
      | 1          | 10         | 1          |
      +------------+------------+------------+
    • 示例2:创建带有聚簇属性的非分区物化视图。

      CREATE MATERIALIZED VIEW mf_mv2 LIFECYCLE 7 
      CLUSTERED BY (key) SORTED BY (value) INTO 1024 buckets 
      AS  SELECT t1.id AS key, t1.value AS value, t1.ds AS ds 
            FROM mf_t AS t1 JOIN mf_t1 AS t2 
              ON t1.id = t2.id AND t1.ds=t2.ds AND t1.ds='1';
    • 示例3:创建带有聚簇属性的分区物化视图。

      CREATE MATERIALIZED VIEW mf_mv3 LIFECYCLE 7 
      PARTITIONED ON (ds) 
      CLUSTERED BY (key) SORTED BY (value) INTO 1024 buckets 
      AS  SELECT t1.id AS key, t1.value AS value, t1.ds AS ds 
            FROM mf_t AS t1 JOIN mf_t1 AS t2 
              ON t1.id = t2.id AND t1.ds=t2.ds AND t1.ds='1';

改写物化视图

场景:假设有一张页面访问表visit_records,记录了各个用户访问的页面ID、用户ID、访问时间。用户经常要对不同页面的访问量进行查询分析。visit_records的结构如下。

+------------------------------------------------------------------------------------+
| Field           | Type       | Label | Comment                                     |
+------------------------------------------------------------------------------------+
| page_id         | string     |       |                                             |
| user_id         | string     |       |                                             |
| visit_time      | string     |       |                                             |
+------------------------------------------------------------------------------------+

此时,可以给visit_records表创建一个以页面ID分组,统计各个页面访问次数的物化视图,并基于物化视图执行后续查询操作:

  1. 执行如下语句创建物化视图。

    CREATE MATERIALIZED VIEW count_mv AS SELECT page_id, count(*) FROM visit_records GROUP BY page_id;
  2. 执行查询语句如下。

    SET odps.sql.materialized.view.enable.auto.rewriting=true; 
    SELECT page_id, count(*) FROM visit_records GROUP BY page_id;

    执行该查询语句时,MaxCompute能自动匹配到物化视图count_mv,从count_mv中读取聚合好的数据。

  3. 执行如下命令检验查询语句是否匹配到物化视图。

    EXPLAIN SELECT page_id, count(*) FROM visit_records GROUP BY page_id;

    返回结果如下。

    job0 is root job
    
    In Job job0:
    root Tasks: M1
    
    In Task M1:
        Data source: doc_test_dev.count_mv
        TS: doc_test_dev.count_mv
            FS: output: Screen
                schema:
                  page_id (string)
                  _c1 (bigint)
    
    
    OK

    从返回结果中的Data source可查看到当前查询读取的表是doc_test_dev项目下的count_mv,说明物化视图有效,查询改写成功。

基于物化视图执行查询改写操作

物化视图最重要的作用就是对查询语句进行查询改写,如果期望查询语句能利用物化视图进行查询改写,则需要在查询语句前添加set odps.sql.materialized.view.enable.auto.rewriting=true;配置。当物化视图处于失效状态时无法用于查询改写,查询语句会直接查询源表而无法获得加速作用。

说明

默认每个MaxCompute项目只能利用自身的物化视图进行查询改写,如果需要利用其他项目中的物化视图进行改写,您需要在查询语句前添加set odps.sql.materialized.view.source.project.white.list=<project_name1>,<project_name2>,<project_name3>;配置指定其他MaxCompute项目列表。

MaxCompute中物化视图的查询改写支持的算子类型及与其他产品的对照关系如下。

算子类型

分类

MaxCompute

BigQuery

Amazon RedShift

Hive

FILTER

表达式完全匹配

支持

支持

支持

支持

表达式部分匹配

支持

支持

支持

支持

AGGREGATE

单个AGGREGATE

支持

支持

支持

支持

多个AGGREGATE

不支持

不支持

不支持

不支持

JOIN

JOIN类型

INNER JOIN

不支持

INNER JOIN

INNER JOIN

单个JOIN

支持

不支持

支持

支持

多个JOIN

支持

不支持

支持

支持

AGGREGATE+JOIN

-

支持

不支持

支持

支持

使用物化视图查询改写的原则是查询语句中需要的数据必须从物化视图中得到,包括输出列、筛选条件中需要的列、聚合函数需要的列、JOIN条件需要的列。如果查询语句中需要的列不包含在物化视图中或聚合函数不支持,则无法基于物化视图进行查询改写。

改写带过滤条件的查询语句

  1. 创建物化视图示例如下。

    CREATE MATERIALIZED VIEW mv AS SELECT a,b,c FROM src WHERE a>5;
  2. 基于创建的物化视图执行查询语句,查询改写对照如下。

    原始查询语句

    改写后的查询语句

    SELECT a,b FROM src WHERE a>5;
    SELECT a,b FROM mv;
    SELECT a, b FROM src WHERE a=10;
    SELECT a,b FROM mv WHERE a=10;
    SELECT a, b FROM src WHERE a=10 AND b=3;
    SELECT a,b FROM mv WHERE a=10 AND b=3;
    SELECT a, b FROM src WHERE a>3;
    (SELECT a,b FROM src WHERE a>3 AND a<=5) UNION (SELECT a,b FROM mv);
    SELECT a, b FROM src WHERE a=10 AND d=4;

    改写不成功,因为mv中没有d列。

    SELECT d, e FROM src WHERE a=10;

    改写不成功,因为mv中没有d、e列。

    SELECT a, b FROM src WHERE a=1;

    改写不成功,因为mv中没有a=1的数据。

改写带聚合函数的查询语句

  • 如果物化视图的SQL语句和查询语句的聚合Key相同,那么所有聚合函数都可以改写,如果聚合Key不相同,只支持SUMMINMAX

    1. 创建的物化视图如下。

      CREATE MATERIALIZED VIEW mv AS 
      SELECT a, b, sum(c) AS sum, count(d) AS cnt FROM src GROUP BY a, b;
    2. 基于创建的物化视图执行查询语句,查询改写对照如下。

      原始查询语句

      改写后的查询语句

      SELECT a, sum(c) FROM src GROUP BY a;
      SELECT a, sum(sum) FROM mv GROUP BY a;
      SELECT a, count(d) FROM src GROUP BY a, b;
      SELECT a, cnt FROM mv;
      SELECT a, count(b) FROM 
      (SELECT a, b FROM src GROUP BY a, b) GROUP BY a;
      SELECT a,count(b) FROM mv GROUP BY a;
      SELECT a,count(b) FROM mv GROUP BY a;

      改写不成功,视图对a、b列进行过聚合,不能再对b进行聚合。

      SELECT a, count(c) FROM src GROUP BY a;

      改写不成功,对于COUNT函数不支持重新聚合。

  • 如果聚合函数中有DISTINCT,当物化视图语句和查询语句聚合Key相同,可以改写,否则不可以改写。

    1. 创建的物化视图如下。

      CREATE MATERIALIZED VIEW mv AS 
      SELECT a, b, sum(DISTINCT c) AS sum, count(DISTINCT d) AS cnt FROM src GROUP BY a, b;
    2. 基于创建的物化视图执行查询语句,查询改写对照如下。

      原始查询语句

      改写后的查询语句

      SELECT a, count(DISTINCT d) FROM src GROUP BY a, b;
      SELECT a, cnt FROM mv;
      SELECT a, count(c) FROM src GROUP BY a, b;

      改写不成功,对于COUNT函数不支持重新聚合。

      SELECT a, count(DISTINCT c) FROM src GROUP BY a;

      改写不成功,因为需要对a再进行聚合。

改写带JOIN的查询语句

  • 改写JOIN输入

    1. 创建的物化视图如下。

      CREATE MATERIALIZED VIEW mv1 AS SELECT a, b FROM j1 WHERE b > 10;
      CREATE MATERIALIZED VIEW mv2 AS SELECT a, b FROM j2 WHERE b > 10;
    2. 基于创建的物化视图执行查询语句,查询改写对照如下。

      原始查询语句

      改写后的查询语句

      SELECT j1.a,j1.b,j2.a FROM (SELECT a,b FROM j1 WHERE b > 10) j1 JOIN j2 ON j1.a=j2.a;
      SELECT mv1.a, mv1.b, j2.a FROM mv1 JOIN j2 ON mv1.a=j2.a;
      SELECT j1.a,j1.b,j2.a FROM 
      (SELECT a,b FROM j1 WHERE b > 10) j1 
      JOIN (SELECT a,b FROM j2 WHERE b > 10) j2 ON j1.a=j2.a;
      SELECT mv1.a,mv1.b,mv2.a FROM mv1 JOIN mv2 ON mv1.a=mv2.a;
  • JOIN带过滤条件

    1. 创建的物化视图如下。

      --创建非分区物化视图。
      CREATE MATERIALIZED VIEW mv1 AS SELECT j1.a, j1.b FROM j1 JOIN j2 ON j1.a=j2.a;
      CREATE MATERIALIZED VIEW mv2 AS SELECT j1.a, j1.b FROM j1 JOIN j2 ON j1.a=j2.a WHERE j1.a > 10;
      --创建分区物化视图。
      CREATE MATERIALIZED VIEW mv LIFECYCLE 7 PARTITIONED BY (ds) AS SELECT t1.id, t1.ds AS ds FROM t1 JOIN t2 ON t1.id = t2.id;
    2. 基于创建的物化视图执行查询语句,查询改写对照如下。

      原始查询语句

      改写后的查询语句

      SELECT j1.a,j1.b FROM j1 JOIN j2 ON j1.a=j2.a WHERE j1.a=4;
      SELECT a, b FROM mv1 WHERE a=4;
      SELECT j1.a,j1.b FROM j1 JOIN j2 ON j1.a=j2.a WHERE j1.a > 20;
      SELECT a,b FROM mv2 WHERE a>20;
      SELECT j1.a,j1.b FROM j1 JOIN j2 ON j1.a=j2.a WHERE j1.a > 5;
      (SELECT j1.a,j1.b FROM j1 JOIN j2 ON j1.a=j2.a WHERE j1.a > 5 AND j1.a <= 10) 
      UNION SELECT * FROM mv2;
      SELECT key FROM t1 JOIN t2 ON t1.id= t2.id WHERE t1.ds='20210306';
      SELECT key FROM mv WHERE ds='20210306';
      SELECT key FROM t1 JOIN t2 ON t1.id= t2.id WHERE t1.ds>='20210306';
      SELECT key FROM mv WHERE ds>='20210306';
      SELECT j1.a,j1.b FROM j1 JOIN j2 ON j1.a=j2.a WHERE j2.a=4;

      改写不成功,因为物化视图没有j2.a列。

  • JOIN增加表

    1. 创建的物化视图如下。

      CREATE MATERIALIZED VIEW mv AS SELECT j1.a, j1.b FROM j1 JOIN j2 ON j1.a=j2.a;
    2. 基于创建的物化视图执行查询语句,查询改写对照如下。

      原始查询语句

      改写后的查询语句

      SELECT j1.a, j1.b FROM j1 JOIN j2 JOIN j3 ON j1.a=j2.a AND j1.a=j3.a;
      SELECT mv.a, mv.b FROM mv JOIN j3 ON mv.a=j3.a;
      SELECT j1.a, j1.b FROM j1 JOIN j2 JOIN j3 ON j1.a=j2.a AND j2.a=j3.a;
      SELECT mv.a,mv.b FROM mv JOIN j3 ON mv.a=j3.a;
说明
  • 以上三种语句可以相互结合,如果查询语句符合改写条件,则可以改写。

  • MaxCompute会选择最佳的改写规则运行,如果改写后增加了一些操作,不是最优运行计划,最终也不会被选中。

改写带LEFT JOIN的查询语句

  1. 创建的物化视图如下。

    CREATE MATERIALIZED VIEW mv LIFECYCLE 7(
            user_id,
            job,
            total_amount
    ) AS SELECT t1.user_id, t1.job, sum(t2.order_amount) AS total_amount 
          FROM user_info AS t1 LEFT JOIN sale_order AS t2 ON t1.user_id=t2.user_id GROUP BY t1.user_id;
  2. 基于创建的物化视图执行查询语句,查询改写对照如下。

    原始查询语句

    改写后的查询语句

    SELECT t1.user_id, sum(t2.order_amout) AS total_amount 
    FROM user_info AS t1 
    LEFT JOIN sale_order AS t2 ON t1.user_id=t2.user_id 
    GROUP BY t1.user_id;
    SELECT user_id, total_amount FROM mv;

改写带UNION ALL的查询语句

  1. 创建的物化视图如下。

    CREATE MATERIALIZED VIEW mv LIFECYCLE 7( 
            user_id, 
            tran_amount, 
            tran_date 
    ) AS SELECT user_id, tran_amount, tran_date FROM alipay_tran UNION ALL 
    SELECT user_id, tran_amount, tran_date FROM unionpay_tran;
  2. 基于创建的物化视图执行查询语句,查询改写对照如下。

    原始查询语句

    改写后的查询语句

    SELECT user_id, tran_amount FROM alipay_tran 
    UNION ALL SELECT user_id, tran_amount FROM unionpay_tran;
    SELECT user_id, total_amount FROM mv;

物化视图查询穿透

对于分区物化视图,不一定所有分区都有数据,可能只刷新了最新的一些分区数据。但用户查询数据时,实际并不知道查询的所有分区数据是否都存在,当查询的分区数据不存在时,需要自动实现到原始分区表去查询数据,流程如下图所示。

查询透穿图示

如果需要物化视图支持穿透查询能力,您需要设置如下参数:

  • 在Session级别设置set odps.optimizer.cbo.rule.filter.black=re;,分区列会被折叠成常量。

  • 创建物化视图时,在tblproperties属性中添加"enable_auto_substitute"="true"配置。

物化视图支持穿透查询示例如下。

  1. 创建物化视图支持分区并且支持查询穿透。

    -- 创建src表。
    CREATE TABLE src(id bigint,name string) PARTITIONED BY (dt string);
    -- 插入数据。
    INSERT INTO src PARTITION(dt='20210101') VALUES(1,'Alex');
    INSERT INTO src PARTITION(dt='20210102') VALUES(2,'Flink');
    
    --将分区列折叠为常量,实现分区动态可变。
    SET odps.optimizer.cbo.rule.filter.black=re;
    --初始化20210101分区数据。
    SET odps.sql.materialized.view.initial.partition={"dt": "20210101"};
    --创建分区物化视图支持穿透。
    CREATE MATERIALIZED VIEW IF NOT EXISTS mv LIFECYCLE 7 
    PARTITIONED ON (dt) 
    tblproperties("enable_auto_substitute"="true") 
    AS SELECT id, name, dt FROM src;
  2. 查询表src中的分区为20210101的数据。

    SELECT * FROM mv WHERE dt='20210101';
  3. 查询物化视图mv中的分区为20210102的数据,自动穿透到源表查询数据。

    SELECT * FROM mv WHERE dt = '20210102';
    --因为20210102的数据没有物化,则需要把查询转化到对应的源表,等价于
    SELECT * FROM (SELECT id, name, dt FROM src WHERE dt='20210102') t;
  4. 查询物化视图mv中分区为20201230~20210102的数据,自动穿透到源表查询的数据与物化视图的数据执行UNION操作后再返回结果。

    SELECT * FROM mv WHERE dt >= '20201230' AND dt<='20210102' AND id='5'; 
    --因为20210102的数据没有物化,则需要把查询转化到对应的源表。等价于:
    SELECT * FROM
    (SELECT id, name, dt FROM src WHERE dt='20211231' OR dt='20210102'
     UNION ALL  
     SELECT * FROM mv WHERE dt='20210101'
    ) t WHERE id = '5';

相关命令