doris rollup

ROLLUP 在多维分析中是“上卷”的意思,即将数据按某种指定的粒度进行进一步聚合。


一、基本概念

  • 在 Doris 中,我们将用户通过建表语句创建出来的表称为 Base 表(Base Table)。Base 表中保存着按用户建表语句指定的方式存储的基础数据。
  • 在 Base 表之上,我们可以创建任意多个 ROLLUP 表。这些 ROLLUP 的数据是基于 Base 表产生的,并且在物理上是独立存储的。
  • ROLLUP 表的基本作用,在于在 Base 表的基础上,获得更粗粒度的聚合数据。

二、Aggregate 和 Uniq 模型中的 ROLLUP

因为 Uniq 只是 Aggregate 模型的一个特例,所以这里我们不加以区别。

2.1 准备数据 

-- step1:建表
CREATE TABLE IF NOT EXISTS test_db.example_site_visit2 (
    `user_id` LARGEINT NOT NULL COMMENT "用户id",
    `date` DATE NOT NULL COMMENT "数据灌入日期时间",
    `timestamp` DATETIME COMMENT "数据灌入时间,精确到秒",
    `city` VARCHAR(20) COMMENT "用户所在城市",
    `age` SMALLINT COMMENT "用户年龄",
    `sex` TINYINT COMMENT "用户性别",
    `last_visit_date` DATETIME REPLACE DEFAULT "1970-01-01 00:00:00" COMMENT "用户最后一次访问时间",
    `cost` BIGINT SUM DEFAULT "0" COMMENT "用户总消费",
    `max_dwell_time` INT MAX DEFAULT "0" COMMENT "用户最大停留时间",
    `min_dwell_time` INT MIN DEFAULT "99999" COMMENT "用户最小停留时
间"
) 
AGGREGATE KEY(`user_id`,`date`,`timestamp`,`city`,`age`,`sex`) 
DISTRIBUTED BY HASH(`user_id`) BUCKETS 10
;


-- step2:插入数据
insert into test_db.example_site_visit2 
values
(10000,'2017-10-01','2017-10-01 08:00:05','北京',20,0,'2017-10-01 06:00:00',20,10,10),
(10000,'2017-10-01','2017-10-01 09:00:05','北京',20,0,'2017-10-01 07:00:00',15,2,2),
(10001,'2017-10-01','2017-10-01 18:12:10','北京',30,1,'2017-10-01 17:05:45',2,22,22),
(10002,'2017-10-02','2017-10-02 13:10:00','上海',20,1,'2017-10-02 12:59:12',200,5,5),
(10003,'2017-10-02','2017-10-02 13:15:00','广州',32,0,'2017-10-02 11:20:00',30,11,11),
(10004,'2017-10-01','2017-10-01 12:12:48','深圳',35,0,'2017-10-01 10:00:15',100,3,3),
(10004,'2017-10-03','2017-10-03 12:38:20','深圳',35,0,'2017-10-03 10:20:22',11,6,6)
;


-- step3:查看表
select * 
from test_db.example_site_visit2
;

-- 可以看到,存储的数据,和导入数据完全一样,没有发生任何聚合。
-- 这是因为,这批数据中,因为加入了 timestamp 列,所有行的 Key 都不完全相同。
-- 也就是说,只要保证导入的数据中, 每一行的 Key 都不完全相同,那么即使在聚合模型下,Doris 也可以保存完整的明细数据。

2.2 查看某个用户的总消费

  • 查看表的结构信息
desc example_site_visit2 all;
  • 比如需要查看某个用户的总消费,那么可以建立一个只有 user_id 和 cost 的 rollup
alter table example_site_visit2 
add rollup 
rollup_cost_userid(user_id,cost);
  • 查看表的结构信息
desc example_site_visit2 all;
  • 然后可以通过 explain 查看执行计划,是否使用到了 rollup
    • Doris 会自动命中这个 ROLLUP 表,从而只需扫描极少的数据量,即可完成这次聚合查询。
explain 
SELECT user_id
	, sum(cost) 
FROM example_site_visit2 
GROUP BY user_id
; 
  • 通过命令查看完成状态
show alter table rollup;
 2.3 获得不同城市,不同年龄段用户的总消费、最长和最短页面驻留时间
  • 创建 ROLLUP
alter table example_site_visit2 
add rollup 
rollup_city_age_cost_maxd_mind(city,age,cost,max_dwell_time,min_dwell_time);
 
  • 查看 rollup 使用
explain
SELECT city,
    age,
    sum(cost),
    max(max_dwell_time),
    min(min_dwell_time)
FROM example_site_visit2
GROUP BY city,
        age
;

explain
SELECT city,
    sum(cost),
    max(max_dwell_time),
    min(min_dwell_time)
FROM example_site_visit2
GROUP BY city
;

explain
SELECT city,
    age,
    sum(cost),
    min(min_dwell_time)
FROM example_site_visit2
GROUP BY city,
        age
;
  • 通过命令查看完成状态
show alter table rollup;

三、Duplicate 模型中的 ROLLUP

  • 因为 Duplicate 模型没有聚合的语意。所以该模型中的 ROLLUP,已经失去了“上卷” 这一层含义。而仅仅是作为调整列顺序,以命中前缀索引的作用
  • 下面详细介绍前缀索引, 以及如何使用 ROLLUP 改变前缀索引,以获得更好的查询效率。
3.1 前缀索引
  • 不同于传统的数据库设计,Doris 不支持在任意列上创建索引。Doris 这类 MPP 架构的 OLAP 数据库,通常都是通过提高并发,来处理大量数据的。
  • 本质上,Doris 的数据存储在类似 SSTable(Sorted String Table)的数据结构中。该结构是一种有序的数据结构,可以按照指定的列进行排序存储。在这种数据结构上,以排序列作为条件进行查找,会非常的高效。
  • 在 Aggregate、Uniq 和 Duplicate 三种数据模型中。底层的数据存储,是按照各自建表语句中,AGGREGATE KEY、UNIQ KEY 和 DUPLICATE KEY 中指定的列进行排序存储 的。而前缀索引,即在排序的基础上,实现的一种根据给定前缀列,快速查询数据的索引方式。
  • 我们将一行数据的前 36 个字节 作为这行数据的前缀索引。当遇到 VARCHAR 类型 时,前缀索引会直接截断。
  • 举例说明:
  • 以下表结构的前缀索引为 user_id(8 Bytes) + age(4 Bytes) + message(prefix 20 Bytes)。
ColumnNameType
user_idBIGINT
ageINT
messageVARCHAR(100)
max_dwell_timeDATETIME
min_dwell_timeDATETIME
  • 以下表结构的前缀索引为 user_name(20 Bytes)。即使没有达到 36 个字节,因为遇到 VARCHAR,所以直接截断,不再往后继续。
ColumnNameType
user_nameVARCHAR(20)
ageINT
messageVARCHAR(100)
max_dwell_timeDATETIME
min_dwell_timeDATETIME
  • 当我们的查询条件,是前缀索引的前缀时,可以极大的加快查询速度。
    • 所以在建表时,正确的选择列顺序,能够极大地提高查询效率。
比如在第一个例子中,我们执行如下查询:
SELECT * 
FROM table 
WHERE user_id=1829239 and age=20
;

该查询的效率会远高于如下查询:

SELECT * 
FROM table 
WHERE age=20
;

3.2 ROLLUP 调整前缀索引

  • 因为建表时已经指定了列顺序,所以一个表只有一种前缀索引。这对于使用其他不能命中前缀索引的列作为条件进行的查询来说,效率上可能无法满足需求。因此,我们可以通过 创建 ROLLUP 来人为的调整列顺序
  • 举例说明。
  • Base 表结构如下:
ColumnNameType
user_idBIGINT
ageINT
messageVARCHAR(100)
max_dwell_timeDATETIME
min_dwell_timeDATETIME
  • 我们可以在此基础上创建一个 ROLLUP 表:
ColumnNameType
ageINT
user_idBIGINT
messageVARCHAR(100)
max_dwell_timeDATETIME
min_dwell_timeDATETIME
  • 可以看到,ROLLUP 和 Base 表的列完全一样,只是将 user_id 和 age 的顺序调换了。那么当我们进行如下查询时:
    • 会优先选择 ROLLUP 表,因为 ROLLUP 的前缀索引匹配度更高。
SELECT * 
FROM table 
where age=20 and message LIKE "%error%"
;

四、ROLLUP 的几点说明

  • ROLLUP 最根本的作用是提高某些查询的查询效率(无论是通过聚合来减少数据量,还是修改列顺序以匹配前缀索引)。因此 ROLLUP 的含义已经超出了“上卷” 的范围。这也是为什么在源代码中,将其命名为 Materialized Index(物化索引)的原因。
  • ROLLUP是附属于Base表的,可以看做是Base表的一种辅助数据结构。用户可以 在 Base 表的基础上,创建或删除 ROLLUP,但是不能在查询中显式的指定查询某 ROLLUP。是否命中 ROLLUP 完全由 Doris 系统自动决定。
  • ROLLUP的数据是独立物理存储的。因此,创建的ROLLUP越多,占用的磁盘空间也就越大。同时对导入速度也会有影响(导入的 ETL 阶段会自动产生所有 ROLLUP 的数据),但是不会降低查询效率(只会更好)。
  • ROLLUP的数据更新与Base表是完全同步的。用户无需关心这个问题。
  • ROLLUP中列的聚合方式,与Base表完全相同。在创建ROLLUP无需指定,也不能修改。
  • 查询能否命中 ROLLUP 的一个必要条件(非充分条件)是,查询所涉及的所有列(包括 select list 和 where 中的查询条件列等)都存在于该 ROLLUP 的列中。否则,查询只能命中 Base 表。
  • 某些类型的查询(如count(*))在任何条件下,都无法命中ROLLUP。
  • 可以通过 EXPLAIN your_sql; 命令获得查询执行计划,在执行计划中,查看是否命中 ROLLUP。
  • 可以通过 DESC tbl_name ALL; 语句显示 Base 表和所有已创建完成的 ROLLUP。

原文链接:Doris--Rollup_doris rollup-CSDN博客

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值