猿创征文|Apache Doris物化视图介绍

1.什么是物化视图

物化视图,简单来说就是预先存储查询结果的一种数据库对象。众所周知 Apache Doris 是一款MPP分析型数据仓库,仅需压秒级就可以快速响应用户的查询需求。物化视图的出现,主要是为了满足用户的需求,对那些频繁使用的重复性的查询,可以提前将查询结果存储在一张特殊的表中,当用户再次使用相同查询需求时,可以自动命中预先处理好的数据,因而能大幅度提升查询效率。

2.物化视图的使用场景

Apache Doris有3种数据模型:唯一主键模型,聚合模型和明细模型。在物化视图出现之前,Doris是采用Rollup来做预聚合提升查询效率的。但Rollup有一个明显的缺点就是它无法对明细数据模型做预聚合操作。物化视图弥补了Rollup的不足,它可以针对Doris的任意模型做预聚合操作,使用范围更加广泛,可以说物化视图是Rollup的升级版。同时Doris自动维护物化视图的数据,无论是新的导入,还是删除操作都能保证base 表和物化视图表的数据一致性。无需任何额外的人工维护成本。

物化视图既能明细数据的任意维度分析,也能快速的对固定维度进行分析查询。当查询需求只包含很少列或行时,或者查询base表需要做聚合等操作时都可以使用物化视图来提升你的查询效率。

3.物化视图的命中规则

用户对base表创建完物化视图之后,SQL请求依然是对base表来进行操作的。但Doris内部会自动判断该SQL请求在是否能够命中物化视图,如果无法命中base表的所有物化视图,则SQL还是会去查询base表;相反,当SQL命中物化视图时,查询结果就会直接从物化视图的预聚合表种获取。那么SQL请求到底是如何命中物化视图的呢?

首先,是对物化视图候选集合<List>的选择。只要SQL查询结果能从物化视图的表中获取到(部分行,部分列或者部分行列的聚合等)的数据,那么它就是一个候选集。

其次就是从候选集合中选择一个最优的物化视图(消耗时间最短的)来返回请求结果。

3.1候选集的选择:

候选集的选择主要分为4步:

第一步:判断SQL请求where中的谓词数据是否能够从物化视图中获取到;

第二步:判断SQL请求中的分组列是否为物化视图列的子集;

第三步:判断SQL请求中的聚合列是否为物化视图列的子集;

第四步:判断SQL请求中的查询列是否为物化视图列的子集。

当物化视图中的所有列都满足SQL查询请求的标准时,我们就可以判断它为一个候选集。

3.2最优选择物化视图:

当候选集合<List>出现后,就需要根据前缀索引是否能匹配到,以及聚合程度的高低来选出一个最优的物化视图。

4.物化视图支持的聚合函数

目前物化视图创建语句支持的聚合函数有:

  • SUM, MIN, MAX (Version 0.12)
  • COUNT, BITMAP_UNION, HLL_UNION (Version 0.13)
  • BITMAP_UNION 的形式必须为:BITMAP_UNION(TO_BITMAP(COLUMN)) column 列的类型只能是整数(largeint也不支持), 或者 BITMAP_UNION(COLUMN) 且 base 表为 AGG 模型。
  • HLL_UNION 的形式必须为:HLL_UNION(HLL_HASH(COLUMN)) column 列的类型不能是 DECIMAL , 或者 HLL_UNION(COLUMN) 且 base 表为 AGG 模型。
5.物化视图的创建及使用
5.1创建物化视图

doris_sql_audit上创建一个名为t_select_counts_per_min的物化视图,该物化视图主要是来分析每秒的查询次数。

CREATE materialized view t_select_counts_per_min as SELECT time , sum(is_query) select_counts FROM doris_sql_audit  GROUP BY time 
5.2查看物化视图

使用desc doris_sql_audit all来查看doris_sql_audit的物化视图

mysql> desc  `doris_sql_audit` all;
+----------------------------------+---------------+------------------------------------------------+-------------+------+-------+---------+-------+---------+
| IndexName                        | IndexKeysType | Field                                          | Type        | Null | Key   | Default | Extra | Visible |
+----------------------------------+---------------+------------------------------------------------+-------------+------+-------+---------+-------+---------+
| doris_sql_audit                  | DUP_KEYS      | query_id                                       | VARCHAR(48) | Yes  | true  | NULL    |       | true    |
|                                  |               | time                                           | DATETIME    | No   | false | NULL    | NONE  | true    |
|                                  |               | client_ip                                      | VARCHAR(32) | Yes  | false | NULL    | NONE  | true    |
|                                  |               | user                                           | VARCHAR(64) | Yes  | false | NULL    | NONE  | true    |
|                                  |               | db                                             | VARCHAR(96) | Yes  | false | NULL    | NONE  | true    |
|                                  |               | state                                          | VARCHAR(8)  | Yes  | false | NULL    | NONE  | true    |
|                                  |               | query_time                                     | BIGINT      | Yes  | false | NULL    | NONE  | true    |
|                                  |               | scan_bytes                                     | BIGINT      | Yes  | false | NULL    | NONE  | true    |
|                                  |               | scan_rows                                      | BIGINT      | Yes  | false | NULL    | NONE  | true    |
|                                  |               | return_rows                                    | BIGINT      | Yes  | false | NULL    | NONE  | true    |
|                                  |               | stmt_id                                        | INT         | Yes  | false | NULL    | NONE  | true    |
|                                  |               | is_query                                       | TINYINT     | Yes  | false | NULL    | NONE  | true    |
|                                  |               | frontend_ip                                    | VARCHAR(32) | Yes  | false | NULL    | NONE  | true    |
|                                  |               | stmt                                           | TEXT        | Yes  | false | NULL    | NONE  | true    |
|                                  |               | cpu_time_ms                                    | BIGINT      | Yes  | false | NULL    | NONE  | true    |
|                                  |               | sql_hash                                       | VARCHAR(48) | Yes  | false | NULL    | NONE  | true    |
|                                  |               | peak_memory_bytes                              | BIGINT      | Yes  | false | NULL    | NONE  | true    |
|                                  |               |                                                |             |      |       |         |       |         |
| t_select_counts_per_user_seconds | AGG_KEYS      | time                                           | DATETIME    | No   | true  | NULL    |       | true    |
|                                  |               | user                                           | VARCHAR(64) | Yes  | true  | NULL    |       | true    |
|                                  |               | is_query                                       | TINYINT     | Yes  | false | NULL    | SUM   | true    |
|                                  |               |                                                |             |      |       |         |       |         |
| t_total_counts_per_seconds       | AGG_KEYS      | time                                           | DATETIME    | No   | true  | NULL    |       | true    |
|                                  |               | CASE WHEN `is_query` IS NULL THEN 0 ELSE 1 END | BIGINT      | No   | false |         | SUM   | true    |
|                                  |               |                                                |             |      |       |         |       |         |
| t_select_counts_per_seconds      | AGG_KEYS      | time                                           | DATETIME    | No   | true  | NULL    |       | true    |
|                                  |               | is_query                                       | TINYINT     | Yes  | false | NULL    | SUM   | true    |
+----------------------------------+---------------+------------------------------------------------+-------------+------+-------+---------+-------+---------+

5.3分析profile,查看是否命中物化视图

可以看到,我们的SQL请求还是对doris_sql_audit表的查询,但根据profile可以看到(在OlapScanNode节点的 rollup: t_select_counts_per_seconds 中),自动命中了t_select_counts_per_seconds物化视图。

mysql> EXPLAIN SELECT DATE_FORMAT(time,'%Y-%m-%d %H:%i:00') time ,sum(is_query) select_counts FROM doris_sql_audit WHERE  time  > day_floor(CURDATE())  AND time <= day_cei
l(CURDATE()) GROUP BY time  ORDER BY time ;+---------------------------------------------------------------------------------------------------------------+
| Explain String                                                                                                |
+---------------------------------------------------------------------------------------------------------------+
| PLAN FRAGMENT 0                                                                                               |
|  OUTPUT EXPRS:<slot 4> <slot 2> date_format(`time`, '%Y-%m-%d %H:%i:00') | <slot 5> <slot 3> sum(`is_query`)  |
|   PARTITION: UNPARTITIONED                                                                                    |
|                                                                                                               |
|   RESULT SINK                                                                                                 |
|                                                                                                               |
|   5:MERGING-EXCHANGE                                                                                          |
|      limit: 65535                                                                                             |
|                                                                                                               |
| PLAN FRAGMENT 1                                                                                               |
|  OUTPUT EXPRS:                                                                                                |
|   PARTITION: HASH_PARTITIONED: <slot 2> date_format(`time`, '%Y-%m-%d %H:%i:00')                              |
|                                                                                                               |
|   STREAM DATA SINK                                                                                            |
|     EXCHANGE ID: 05                                                                                           |
|     UNPARTITIONED                                                                                             |
|                                                                                                               |
|   2:TOP-N                                                                                                     |
|   |  order by: <slot 4> <slot 2> date_format(`time`, '%Y-%m-%d %H:%i:00') ASC                                 |
|   |  offset: 0                                                                                                |
|   |  limit: 65535                                                                                             |
|   |                                                                                                           |
|   4:AGGREGATE (merge finalize)                                                                                |
|   |  output: sum(<slot 3> sum(`is_query`))                                                                    |
|   |  group by: <slot 2> date_format(`time`, '%Y-%m-%d %H:%i:00')                                              |
|   |  cardinality=-1                                                                                           |
|   |                                                                                                           |
|   3:EXCHANGE                                                                                                  |
|                                                                                                               |
| PLAN FRAGMENT 2                                                                                               |
|  OUTPUT EXPRS:                                                                                                |
|   PARTITION: RANDOM                                                                                           |
|                                                                                                               |
|   STREAM DATA SINK                                                                                            |
|     EXCHANGE ID: 03                                                                                           |
|     HASH_PARTITIONED: <slot 2> date_format(`time`, '%Y-%m-%d %H:%i:00')                                       |
|                                                                                                               |
|   1:AGGREGATE (update serialize)                                                                              |
|   |  STREAMING                                                                                                |
|   |  output: sum(`is_query`)                                                                                  |
|   |  group by: date_format(`time`, '%Y-%m-%d %H:%i:00')                                                       |
|   |  cardinality=-1                                                                                           |
|   |                                                                                                           |
|   0:OlapScanNode                                                                                              |
|      TABLE: doris_sql_audit                                                                                   |
|      PREAGGREGATION: ON                                                                                       |
|      PREDICATES: `time` > day_floor('2022-06-09'), `time` <= day_ceil('2022-06-09')                           |
|      partitions=89/94                                                                                         |
|      rollup: t_select_counts_per_seconds                                                                      |
|      tabletRatio=89/89                                                                                        |
|      tabletList=17862694,17863998,17862510,17862806,17862214,17863826,17862954,17863590,17863990,17863770 ... |
|      cardinality=5200524                                                                                      |
|      avgRowSize=1.7375114                                                                                     |
|      numNodes=10                                                                                              |
+---------------------------------------------------------------------------------------------------------------+
54 rows in set (0.01 sec)
5.4删除物化视图
DROP MATERIALIZED VIEW  t_select_counts_per_min ON doris_sql_audit;
  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值