Apache Doris——物化视图

八、物化视图

物化视图就是包含了查询结果的数据库对象,可能是对远程数据的本地copy,也可能是一个表或多表join后结果的行或列的子集,也可能是聚合后的结果。说白了,就是预先存储查询结果的一种数据库对象。

在Doris中的物化视图,就是查询结果预先存储起来的特殊的表。
物化视图的出现主要是为了满足用户,既能对原始明细数据的任意维度分析,也能快速的对固定维度进行分析查询。

适用场景

  • 1、分析需求覆盖明细数据查询以及固定维度查询两方面;
  • 2、查询仅涉及表中的很小一部分列或行;
  • 3、查询包含一些耗时处理操作,比如:时间很久的聚合操作等;
  • 4、查询需要匹配不同前缀索引。

优势

  • 1、对于那些经常重复的使用相同的子查询结果的查询性能大幅提升;
  • 2、Doris自动维护物化视图的数据,无论是新的导入,还是删除操作都能保证base表和物化视图表的数据一致性。无需任何额外的人工维护成本;
  • 3、查询时,会自动匹配到最优物化视图,并直接从物化视图中读取数据。

自动维护物化视图的数据会造成一些维护开销,会在后面的物化视图的局限性中展开说明。

物化视图和Rollup

在没有物化视图功能之前,用户一般都是使用Rollup功能通过预聚合方式提升查询效率的。但是 Rollup具有一定的局限性,他不能基于明细模型做预聚合。

物化视图则在覆盖了Rollup的功能的同时,还能支持更丰富的聚合函数。所以物化视图其实是Rollup的一个超集。也就是说,之前ALTER TABLE ADD ROLLUP语法支持的功能现在均可以通CREATE MATERIALIZED VIEW实现。

原理

Doris系统提供了一整套对物化视图的DDL语法,包括创建,查看,删除。DDL 的语法和PostgreSQL, Oracle都是一致的。但是Doris目前创建物化视图只能在单表操作,不支持join。

创建物化视图

首先要根据查询语句的特点来决定创建一个什么样的物化视图。并不是说物化视图定义和某个查询语句一模一样就最好。这里有两个原则:

  • 从查询语句中抽象出,多个查询共有的分组和聚合方式作为物化视图的定义;
  • 不需要给所有维度组合都创建物化视图。

第一点,一个物化视图如果抽象出来,并且多个查询都可以匹配到这张物化视图。这种物化视图效果最好,因为物化视图的维护本身也需要消耗资源。如果物化视图只和某个特殊的查询很贴合,而其他查询均用不到这个物化视图。则会导致这张物化视图的性价比不高,既占用了集群的存储资源,还不能为更多的查询服务。所以用户需要结合自己的查询语句,以及数据维度信息去抽象出一些物化视图的定义。

第二点,在实际的分析查询中,并不会覆盖到所有的维度分析。所以给常用的维度组合创建物化视图即可,从而到达一个空间和时间上的平衡。

通过下面命令就可以创建物化视图了。创建物化视图是一个异步的操作,也就是说用户成功提交创建任务后,Doris会在后台对存量的数据进行计算,直到创建成功。
具体的语法可以通过下面命令查看:HELP CREATE MATERIALIZED VIEW,这里以一个销售记录表为例:


比如我们有一张销售记录明细表,存储了每个交易的时间,销售员,销售门店,和金额。提交完创建物化视图的任务后,Doris就会异步在后台生成物化视图的数据,构建物化视图。在构建期间,用户依然可以正常的查询和导入新的数据。创建任务会自动处理当前的存量数据和所有新到达的增量数据,从而保持和base表的数据一致性。用户不需关心一致性问题。

查询

物化视图创建完成后,用户的查询会根据规则自动匹配到最优的物化视图。比如我们有一张销售记录明细表,并且在这个明细表上创建了三张物化视图。一个存储了不同时间不同销售员的售卖量,一个存储了不同时间不同门店的销售量,以及每个销售员的总销售量。当查询7月19日,各个销售员都买了多少钱时,就可以匹配mv_1物化视图,直接对mv_1 的数据进行查询。

查询自动匹配

物化视图的自动匹配分为下面两个步骤:

  • 1、根据查询条件删选出一个最优的物化视图:这一步的输入是所有候选物化视图表的元数据,根据查询的条件从候选集中输出最优的一个物化视图;
    *2、根据选出的物化视图对查询进行改写:这一步是结合上一步选择出的最优物化视图,进行查询的改写,最终达到直接查询物化视图的目的。

其中bitmap和hll的聚合函数在查询匹配到物化视图后,查询的聚合算子会根据物化视图的表结构进行改写,如物化视图的查询所示。

最优路径选择

这里分为两个步骤:

  • 1、对候选集合进行一个过滤。只要是查询的结果能从物化视图数据计算(取部分行,部分列,或部分行列的聚合)出都可以留在候选集中,过滤完成后候选集合大小>=1。
  • 2、从候选集合中根据聚合程度,索引等条件选出一个最优的也就是查询花费最少物化视图。

这里再举一个相对复杂的例子,来体现这个过程:


候选集过滤目前分为4层,每一层过滤后去除不满足条件的物化视图。比如查询7月19日,各个销售员都卖了多少钱,候选集中包括所有的物化视图以及base表共4个:
第一层过滤先判断查询where中的谓词涉及到的数据是否能从物化视图中得到。也就是销售时间列是否在表中存在。由于第三个物化视图中根本不存在销售时间列。所以在这一层过滤中,mv_3就被淘汰了;
第二层是过滤查询的分组列是否为候选集的分组列的子集。也就是销售员id是否为表中分组列的子集。由于第二个物化视图中的分组列并不涉及销售员id。所以在这一层过滤中,mv_2也被淘汰了;
第三层过滤是看查询的聚合列是否为候选集中聚合列的子集。也就是对销售额求和是否能从候选集的表中聚合得出。这里base表和物化视图表均满足标准;
最后一层是过滤看查询需要的列是否存在于候选集合的列中。由于候选集合中的表均满足标准,所以最终候选集合中的表为销售明细表,以及mv_1。

候选集过滤完后输出一个集合,这个集合中的所有表都能满足查询的需求。但每张表的查询效率都不同。这时候就需要再这个集合根据前缀索引是否能匹配到,以及聚合程度的高低来选出一个最优的物化视图。

从表结构中可以看出,base表的销售日期列是一个非排序列,而物化视图表的日期是一个排序列,同时聚合程度上mv_1表明显比base表高。所以最后选择出mv_1作为该查询的最优匹配。

最后再根据选择出的最优解,改写查询。刚才的查询选中mv_1后,将查询改写为从mv_1中读取数据,过滤出日志为7月19日的mv_1中的数据然后返回即可。

查询改写

有些情况下的查询改写还会涉及到查询中的聚合函数的改写,比如业务方经常会用到count distinct对PV、UV进行计算。

例如:广告点击明细记录表中存放哪个用户点击了什么广告,从什么渠道点击的,以及点击的时间。并且在这个base表基础上构建了一个物化视图表,存储了不同广告不同渠道的用户bitmap 值。由于bitmap union这种聚合方式本身会对相同的用户user id进行一个去重聚合。当用户查询广告在web端的uv的时候,就可以匹配到这个物化视图。匹配到这个物化视图表后就需要对查询进行改写,将之前的对用户id求count(distinct)改为对物化视图中bitmap union列求count。所以最后查询取物化视图的第一和第三行求bitmap聚合中有几个值。

使用及限制

  • 1、目前支持的聚合函数包括,常用的sum,min,max count,以及计算pv ,uv,留存率,等常用的去重算法hll_union,和用于精确去重计算count(distinct)的算法bitmap_union;
  • 2、物化视图的聚合函数的参数不支持表达式仅支持单列,比如: sum(a+b)不支持;
  • 3、使用物化视图功能后,由于物化视图实际上是损失了部分维度数据的。所以对表的DML类型操作会有一些限制:如果表的物化视图key中不包含删除语句中的条件列,则删除语句不能执行。比如想要删除渠道为app端的数据,由于存在一个物化视图并不包含渠道这个字段,则这个删除不能执行,因为删除在物化视图中无法被执行。这时候你只能把物化视图先删除,然后删除完数据后,重新构建一个新的物化视图;
  • 4、单表上过多的物化视图会影响导入的效率:导入数据时,物化视图和base表数据是同步更新的,如果一张表的物化视图表超过10张,则有可能导致导入速度很慢。这就像单次导入需要同时导入10张表数据是一样的;
  • 5、相同列,不同聚合函数,不能同时出现在一张物化视图中,比如:select sum(a),min(a) from table不支持;
  • 6、物化视图针对Unique Key数据模型,只能改变列顺序,不能起到聚合的作用,所以在Unique Key模型上不能通过创建物化视图的方式对数据进行粗粒度聚合操作。

示例

示例1

创建表:

create table sales_records(
    record_id int,
    seller_id int,
    store_id int,
    sale_date date,
    sale_amt bigint
)
distributed by hash(record_id)
properties("replication_num" = "1");

插入数据:

insert into sales_records values(1,2,3,'2020-02-02',10);

创建物化视图:

create materialized view store_amt as select store_id, sum(sale_amt) from sales_records group by store_id;

由于创建物化视图是一个异步的操作,用户在提交完创建物化视图任务后,需要异步地通过命令检查物化视图是否构建完成:

mysql> SHOW ALTER TABLE MATERIALIZED VIEW FROM test;
+-------+---------------------+---------------------+---------------------+---------------------+--------------------------------+----------+---------------+----------+------+----------+---------+
| JobId | TableName           | CreateTime          | FinishTime          | BaseIndexName       | RollupIndexName                | RollupId | TransactionId | State    | Msg  | Progress | Timeout |
+-------+---------------------+---------------------+---------------------+---------------------+--------------------------------+----------+---------------+----------+------+----------+---------+
| 10599 | example_site_visit2 | 2022-05-14 16:25:23 | 2022-05-14 16:25:44 | example_site_visit2 | rollup_cost_userid             | 10600    | 12            | FINISHED |      | NULL     | 86400   |
| 10621 | example_site_visit2 | 2022-05-14 16:27:54 | 2022-05-14 16:28:24 | example_site_visit2 | rollup_city_age_cost_maxd_mind | 10622    | 13            | FINISHED |      | NULL     | 86400   |
| 10667 | sales_records       | 2022-05-14 17:56:50 | 2022-05-14 17:57:14 | sales_records       | store_amt                      | 10668    | 15            | FINISHED |      | NULL     | 86400   |
+-------+---------------------+---------------------+---------------------+---------------------+--------------------------------+----------+---------------+----------+------+----------+---------+
3 rows in set (0.00 sec)

检验当前查询是否匹配到了合适的物化视图:

mysql> EXPLAIN SELECT store_id, sum(sale_amt) FROM sales_records GROUP BY store_id;
+-----------------------------------------------------------------------------------+
| Explain String                                                                    |
+-----------------------------------------------------------------------------------+
| PLAN FRAGMENT 0                                                                   |
|  OUTPUT EXPRS:<slot 2> `store_id` | <slot 3> sum(`sale_amt`)                      |
|   PARTITION: UNPARTITIONED                                                        |
|                                                                                   |
|   RESULT SINK                                                                     |
|                                                                                   |
|   4:EXCHANGE                                                                      |
|                                                                                   |
| PLAN FRAGMENT 1                                                                   |
|  OUTPUT EXPRS:                                                                    |
|   PARTITION: HASH_PARTITIONED: <slot 2> `store_id`                                |
|                                                                                   |
|   STREAM DATA SINK                                                                |
|     EXCHANGE ID: 04                                                               |
|     UNPARTITIONED                                                                 |
|                                                                                   |
|   3:AGGREGATE (merge finalize)                                                    |
|   |  output: sum(<slot 3> sum(`sale_amt`))                                        |
|   |  group by: <slot 2> `store_id`                                                |
|   |  cardinality=-1                                                               |
|   |                                                                               |
|   2:EXCHANGE                                                                      |
|                                                                                   |
| PLAN FRAGMENT 2                                                                   |
|  OUTPUT EXPRS:                                                                    |
|   PARTITION: HASH_PARTITIONED: `default_cluster:test`.`sales_records`.`record_id` |
|                                                                                   |
|   STREAM DATA SINK                                                                |
|     EXCHANGE ID: 02                                                               |
|     HASH_PARTITIONED: <slot 2> `store_id`                                         |
|                                                                                   |
|   1:AGGREGATE (update serialize)                                                  |
|   |  STREAMING                                                                    |
|   |  output: sum(`sale_amt`)                                                      |
|   |  group by: `store_id`                                                         |
|   |  cardinality=-1                                                               |
|   |                                                                               |
|   0:OlapScanNode                                                                  |
|      TABLE: sales_records                                                         |
|      PREAGGREGATION: ON                                                           |
|      partitions=1/1                                                               |
|      rollup: store_amt                                                            |
|      tabletRatio=10/10                                                            |
|      tabletList=10669,10671,10673,10675,10677,10679,10681,10683,10685,10687       |
|      cardinality=0                                                                |
|      avgRowSize=12.0                                                              |
|      numNodes=1                                                                   |
+-----------------------------------------------------------------------------------+
47 rows in set (0.01 sec)

删除物化视图:

DROP MATERIALIZED VIEW 物化视图名 on Base表名;

案例2:计算pv和uv

假设用户的原始广告点击数据存储在Doris,那么针对广告PV, UV查询就可以通过创建bitmap_union的物化视图来提升查询速度。
创建表:

create table advertiser_view_record(
    time date,
    advertiser varchar(10),
    channel varchar(10),
    user_id int
)
distributed by hash(time)
properties("replication_num" = "1");

插入数据:

insert into advertiser_view_record values('2020-02-02','a','app',123);

创建物化视图:

create materialized view advertiser_uv as
select advertiser, channel, bitmap_union(to_bitmap(user_id))
from advertiser_view_record
group by advertiser, channel;

在Doris中,count(distinct)聚合的结果和bitmap_union_count聚合的结果是完全一致的。而bitmap_union_count等于bitmap_union的结果求count,所以如果查询中涉及到count(distinct)则通过创建带bitmap_union聚合的物化视图方可加快查询。

因为本身user_id是INT类型,所以在Doris中需要先将字段通过函数to_bitmap转换为bitmap类型然后才可以进行bitmap_union聚合。
检验是否匹配到物化视图:

mysql> explain SELECT advertiser, channel, count(distinct user_id) FROM advertiser_view_record GROUP BY advertiser, channel;
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Explain String                                                                                                                                                    |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| PLAN FRAGMENT 0                                                                                                                                                   |
|  OUTPUT EXPRS:<slot 7> `advertiser` | <slot 8> `channel` | <slot 9> bitmap_union_count(`default_cluster:test`.`advertiser_view_record`.`mv_bitmap_union_user_id`) |
|   PARTITION: UNPARTITIONED                                                                                                                                        |
|                                                                                                                                                                   |
|   RESULT SINK                                                                                                                                                     |
|                                                                                                                                                                   |
|   4:EXCHANGE                                                                                                                                                      |
|                                                                                                                                                                   |
| PLAN FRAGMENT 1                                                                                                                                                   |
|  OUTPUT EXPRS:                                                                                                                                                    |
|   PARTITION: HASH_PARTITIONED: <slot 4> `advertiser`, <slot 5> `channel`                                                                                          |
|                                                                                                                                                                   |
|   STREAM DATA SINK                                                                                                                                                |
|     EXCHANGE ID: 04                                                                                                                                               |
|     UNPARTITIONED                                                                                                                                                 |
|                                                                                                                                                                   |
|   3:AGGREGATE (merge finalize)                                                                                                                                    |
|   |  output: bitmap_union_count(<slot 6> bitmap_union_count(`default_cluster:test`.`advertiser_view_record`.`mv_bitmap_union_user_id`))                           |
|   |  group by: <slot 4> `advertiser`, <slot 5> `channel`                                                                                                          |
|   |  cardinality=-1                                                                                                                                               |
|   |                                                                                                                                                               |
|   2:EXCHANGE                                                                                                                                                      |
|                                                                                                                                                                   |
| PLAN FRAGMENT 2                                                                                                                                                   |
|  OUTPUT EXPRS:                                                                                                                                                    |
|   PARTITION: HASH_PARTITIONED: `default_cluster:test`.`advertiser_view_record`.`time`                                                                             |
|                                                                                                                                                                   |
|   STREAM DATA SINK                                                                                                                                                |
|     EXCHANGE ID: 02                                                                                                                                               |
|     HASH_PARTITIONED: <slot 4> `advertiser`, <slot 5> `channel`                                                                                                   |
|                                                                                                                                                                   |
|   1:AGGREGATE (update serialize)                                                                                                                                  |
|   |  STREAMING                                                                                                                                                    |
|   |  output: bitmap_union_count(`default_cluster:test`.`advertiser_view_record`.`mv_bitmap_union_user_id`)                                                        |
|   |  group by: `advertiser`, `channel`                                                                                                                            |
|   |  cardinality=-1                                                                                                                                               |
|   |                                                                                                                                                               |
|   0:OlapScanNode                                                                                                                                                  |
|      TABLE: advertiser_view_record                                                                                                                                |
|      PREAGGREGATION: ON                                                                                                                                           |
|      partitions=1/1                                                                                                                                               |
|      rollup: advertiser_uv                                                                                                                                        |
|      tabletRatio=10/10                                                                                                                                            |
|      tabletList=10715,10717,10719,10721,10723,10725,10727,10729,10731,10733                                                                                       |
|      cardinality=0                                                                                                                                                |
|      avgRowSize=48.0                                                                                                                                              |
|      numNodes=1                                                                                                                                                   |
+-------------------------------------------------------------------------------------------------------------------------------------------------------------------+
47 rows in set (0.01 sec)

在 EXPLAIN 的结果中,首先可以看到OlapScanNode的rollup属性值为advertiser_uv。也就是说,查询会直接扫描物化视图的数据,说明匹配成功。其次对于user_id字段求count(distinct)被改写为求bitmap_union_count(to_bitmap),也就是通过bitmap的方式来达到精确去重的效果。

案例3

用户的原始表有(k1, k2, k3)三列。其中k1, k2为前缀索引列。这时候如果用户查询条件中包含 where k1=1 and k2=2就能通过索引加速查询。但是有些情况下,用户的过滤条件无法匹配到前缀索引,比如where k3=3,则无法通过索引提升查询速度,而创建以k3作为第一列的物化视图就可以解决这个问题。
查询:

mysql> explain select record_id,seller_id,store_id from sales_records where store_id=3;
+-----------------------------------------------------------------------------------+
| Explain String                                                                    |
+-----------------------------------------------------------------------------------+
| PLAN FRAGMENT 0                                                                   |
|  OUTPUT EXPRS:`record_id` | `seller_id` | `store_id`                              |
|   PARTITION: UNPARTITIONED                                                        |
|                                                                                   |
|   RESULT SINK                                                                     |
|                                                                                   |
|   1:EXCHANGE                                                                      |
|                                                                                   |
| PLAN FRAGMENT 1                                                                   |
|  OUTPUT EXPRS:                                                                    |
|   PARTITION: HASH_PARTITIONED: `default_cluster:test`.`sales_records`.`record_id` |
|                                                                                   |
|   STREAM DATA SINK                                                                |
|     EXCHANGE ID: 01                                                               |
|     UNPARTITIONED                                                                 |
|                                                                                   |
|   0:OlapScanNode                                                                  |
|      TABLE: sales_records                                                         |
|      PREAGGREGATION: ON                                                           |
|      PREDICATES: `store_id` = 3                                                   |
|      partitions=1/1                                                               |
|      rollup: sales_records                                                        |
|      tabletRatio=10/10                                                            |
|      tabletList=10646,10648,10650,10652,10654,10656,10658,10660,10662,10664       |
|      cardinality=1                                                                |
|      avgRowSize=923.0                                                             |
|      numNodes=1                                                                   |
+-----------------------------------------------------------------------------------+
27 rows in set (0.01 sec)

创建物化视图:

create materialized view mv_1 as
select
store_id,
record_id,
seller_id,
sale_date,
sale_amt
from sales_records;

通过上面语法创建完成后,物化视图中既保留了完整的明细数据,且物化视图的前缀索引为 store_id列。
查看表结构:

mysql> desc sales_records all;
+---------------+---------------+-----------+--------+------+-------+---------+-------+---------+
| IndexName     | IndexKeysType | Field     | Type   | Null | Key   | Default | Extra | Visible |
+---------------+---------------+-----------+--------+------+-------+---------+-------+---------+
| sales_records | DUP_KEYS      | record_id | INT    | Yes  | true  | NULL    |       | true    |
|               |               | seller_id | INT    | Yes  | true  | NULL    |       | true    |
|               |               | store_id  | INT    | Yes  | true  | NULL    |       | true    |
|               |               | sale_date | DATE   | Yes  | false | NULL    | NONE  | true    |
|               |               | sale_amt  | BIGINT | Yes  | false | NULL    | NONE  | true    |
|               |               |           |        |      |       |         |       |         |
| mv_1          | DUP_KEYS      | store_id  | INT    | Yes  | true  | NULL    |       | true    |
|               |               | record_id | INT    | Yes  | true  | NULL    |       | true    |
|               |               | seller_id | INT    | Yes  | true  | NULL    |       | true    |
|               |               | sale_date | DATE   | Yes  | false | NULL    | NONE  | true    |
|               |               | sale_amt  | BIGINT | Yes  | false | NULL    | NONE  | true    |
|               |               |           |        |      |       |         |       |         |
| store_amt     | AGG_KEYS      | store_id  | INT    | Yes  | true  | NULL    |       | true    |
|               |               | sale_amt  | BIGINT | Yes  | false | NULL    | SUM   | true    |
+---------------+---------------+-----------+--------+------+-------+---------+-------+---------+
14 rows in set (0.00 sec)

查询匹配:

mysql> explain select record_id,seller_id,store_id from sales_records where store_id=3;
+-----------------------------------------------------------------------------------+
| Explain String                                                                    |
+-----------------------------------------------------------------------------------+
| PLAN FRAGMENT 0                                                                   |
|  OUTPUT EXPRS:`record_id` | `seller_id` | `store_id`                              |
|   PARTITION: UNPARTITIONED                                                        |
|                                                                                   |
|   RESULT SINK                                                                     |
|                                                                                   |
|   1:EXCHANGE                                                                      |
|                                                                                   |
| PLAN FRAGMENT 1                                                                   |
|  OUTPUT EXPRS:                                                                    |
|   PARTITION: HASH_PARTITIONED: `default_cluster:test`.`sales_records`.`record_id` |
|                                                                                   |
|   STREAM DATA SINK                                                                |
|     EXCHANGE ID: 01                                                               |
|     UNPARTITIONED                                                                 |
|                                                                                   |
|   0:OlapScanNode                                                                  |
|      TABLE: sales_records                                                         |
|      PREAGGREGATION: ON                                                           |
|      PREDICATES: `store_id` = 3                                                   |
|      partitions=1/1                                                               |
|      rollup: mv_1                                                                 |
|      tabletRatio=10/10                                                            |
|      tabletList=10737,10739,10741,10743,10745,10747,10749,10751,10753,10755       |
|      cardinality=0                                                                |
|      avgRowSize=12.0                                                              |
|      numNodes=1                                                                   |
+-----------------------------------------------------------------------------------+
27 rows in set (0.00 sec)

这时候查询就会直接从刚才创建的mv_1物化视图中读取数据。由于物化视图对store_id是存在前缀索引的,查询效率也会提升。

修改表

使用ALTER TABLE命令可以对表进行修改,包括partition 、rollup、schema change、rename和index五种。语法:

ALTER TABLE [database.]table
alter_clause1[, alter_clause2, ...];
alter_clause 分为 partition 、rollup、schema change、rename 和 index 五种。

rename

将名为 table1的表修改为table2:

ALTER TABLE table1 RENAME table2;

将表example_table中名为rollup1的rollup index修改为rollup2:

ALTER TABLE example_table RENAME ROLLUP rollup1 rollup2;

将表example_table中名为p1的partition修改为p2:

ALTER TABLE example_table RENAME PARTITION p1 p2;

partition

增加分区, 使用默认分桶方式,如现有分区[MIN, 2013-01-01),增加分区[2013-01-01, 2014-01-01):

ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES LESS THAN ("2014-01-01");

增加分区,使用新的分桶数:

ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES LESS THAN ("2015-01-01") DISTRIBUTED BY HASH(k1) BUCKETS 20;

增加分区,使用新的副本数:

ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES LESS THAN ("2015-01-01") ("replication_num"="1");

修改分区副本数:

ALTER TABLE example_db.my_table MODIFY PARTITION p1 SET("replication_num"="1");

批量修改指定分区:

ALTER TABLE example_db.my_table MODIFY PARTITION (p1, p2, p4) SET("in_memory"="true");

批量修改所有分区:

ALTER TABLE example_db.my_table MODIFY PARTITION (*) SET("storage_medium"="HDD");

删除分区:

ALTER TABLE example_db.my_table DROP PARTITION p1;

增加一个指定上下界的分区:

ALTER TABLE example_db.my_table ADD PARTITION p1 VALUES [("2014-01-01"), ("2014-02-01"));

rollup

创建index: example_rollup_index,基于base index(k1,k2,k3,v1,v2),列式存储:

ALTER TABLE example_db.my_table
ADD ROLLUP example_rollup_index(k1, k3, v1, v2);

创建index: example_rollup_index2,基于example_rollup_index(k1,k3,v1,v2):

ALTER TABLE example_db.my_table ADD ROLLUP example_rollup_index2 (k1, v1) FROM example_rollup_index;

创建index: example_rollup_index3, 基于base index (k1,k2,k3,v1), 自定义rollup超时时间一小时:

ALTER TABLE example_db.my_table ADD ROLLUP example_rollup_index(k1, k3, v1) PROPERTIES("timeout" = "3600");

删除index: example_rollup_index2:

ALTER TABLE example_db.my_table DROP ROLLUP example_rollup_index2;

表结构变更

使用ALTER TABLE命令可以修改表的Schema,包括:增加列、删除列、修改列类型、改变列顺序。以增加列为例:
我们新增一列uv,类型为BIGINT,聚合类型为SUM,默认值为0:

ALTER TABLE table1 ADD COLUMN uv BIGINT SUM DEFAULT '0' after pv;

提交成功后,可以通过以下命令查看作业进度:

SHOW ALTER TABLE COLUMN;

当作业状态为FINISHED,则表示作业完成,新的Schema已生效。
查看新的Schema:

DESC table1;

可以使用以下命令取消当前正在执行的作业:

CANCEL ALTER TABLE ROLLUP FROM table1;

更多可以参阅:HELP ALTER TABLE。

删除数据

Doris目前可以通过两种方式删除数据:DELETE FROM语句和ALTER TABLE DROP PARTITION 语句。

条件删除(drop from)

delete from语句类似标准delete语法,具体使用可以查看help delete;帮助。
语法:

DELETE FROM table_name [PARTITION partition_name]
WHERE
column_name1 op { value | value_list } [ AND column_name2 op { value
| value_list } ...];

如:

delete from student_kafka where id=1;

注意事项:

  • 1、该语句只能针对Partition级别进行删除。如果一个表有多个partition含有需要删除的数据,则需要执行多次针对不同Partition的delete 语句。而如果是没有使用Partition的表,partition的名称即表名;
  • 2、where后面的条件谓词只能针对Key列,并且谓词之间,只能通过AND连接。如果想实现OR的语义,需要执行多条delete;
  • 3、delete是一个同步命令,命令返回即表示执行成功;
  • 4、从代码实现角度,delete是一种特殊的导入操作。该命令所导入的内容,也是一个新的数据版本,只是该版本中只包含命令中指定的删除条件。在实际执行查询时,会根据这些条件进行查询时过滤。所以,不建议大量频繁使用delete命令,因为这可能导致查询效率降低;
  • 5、数据的真正删除是在BE进行数据Compaction时进行的。所以执行完delete命令后,并不会立即释放磁盘空间;
  • 6、delete命令一个较强的限制条件是,在执行该命令时,对应的表,不能有正在进行的导入任务(包括PENDING、ETL、LOADING)。而如果有QUORUM_FINISHED状态的导入任务,则可能可以执行;
  • 7、delete也有一个隐含的类似QUORUM_FINISHED的状态。即如果 delete只在多数副本上完成了,也会返回用户成功。但是会在后台生成一个异步的delete job(Async Delete Job),来继续完成对剩余副本的删除操作。如果此时通过show delete命令,可以看到这种任务在state一栏会显示QUORUM_FINISHED。

分区删除(drop partition)

该命令可以直接删除指定的分区。因为Partition是逻辑上最小的数据管理单元,所以使用DROP PARTITION命令可以很轻量地完成数据删除工作,并且不受load以及任何其他操作的限制,同时不会影响查询效率,是比较推荐的一种数据删除方式。该命令是同步命令,执行成功即生效。而后台数据真正删除的时间可能会延迟10分钟左右。

参考:
https://blog.csdn.net/qq_37475168/article/details/125570856

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354

推荐阅读更多精彩内容