Doris专题5- Rollup与查询
1. Rollup基本概念
1.1 核心定义
- Base Table:用户通过建表语句创建的基础表
- ROLLUP表:基于Base表创建的辅助数据结构,物理上独立存储
- 作用:获得更粗粒度的聚合数据或调整列顺序优化查询
1.2 Rollup类型
2. Aggregate模型中的Rollup
2.1 基础表示例
Base表结构:
ColumnName | Type | AggregationType | Comment |
---|---|---|---|
user_id | LARGEINT | - | 用户id |
date | DATE | - | 数据灌入日期 |
timestamp | DATETIME | - | 数据灌入时间 |
city | VARCHAR(20) | - | 用户所在城市 |
age | SMALLINT | - | 用户年龄 |
sex | TINYINT | - | 用户性别 |
last_visit_date | DATETIME | REPLACE | 最后访问时间 |
cost | BIGINT | SUM | 用户总消费 |
max_dwell_time | INT | MAX | 最大停留时间 |
min_dwell_time | INT | MIN | 最小停留时间 |
2.2 Rollup示例1:用户总消费
-- 创建用户消费汇总Rollup
ALTER TABLE table_name ADD ROLLUP rollup_user_cost(user_id, cost);
Rollup数据效果:
user_id | cost |
---|---|
10000 | 35 |
10001 | 2 |
10002 | 200 |
10003 | 30 |
10004 | 111 |
查询自动命中:
SELECT user_id, sum(cost) FROM table GROUP BY user_id;
2.3 Rollup示例2:城市年龄维度聚合
-- 创建城市年龄维度Rollup
ALTER TABLE table_name ADD ROLLUP rollup_city_age(city, age, cost, max_dwell_time, min_dwell_time
);
Rollup数据效果:
city | age | cost | max_dwell_time | min_dwell_time |
---|---|---|---|---|
北京 | 20 | 35 | 10 | 2 |
北京 | 30 | 2 | 22 | 22 |
上海 | 20 | 200 | 5 | 5 |
广州 | 32 | 30 | 11 | 11 |
深圳 | 35 | 111 | 6 | 3 |
可命中的查询:
-- 查询1:城市+年龄维度聚合
SELECT city, age, sum(cost), max(max_dwell_time), min(min_dwell_time)
FROM table GROUP BY city, age;-- 查询2:城市维度聚合
SELECT city, sum(cost), max(max_dwell_time), min(min_dwell_time)
FROM table GROUP BY city;-- 查询3:城市+年龄维度部分聚合
SELECT city, age, sum(cost), min(min_dwell_time)
FROM table GROUP BY city, age;
3. Duplicate模型中的Rollup
3.1 前缀索引优化
Base表结构:
ColumnName | Type |
---|---|
user_id | BIGINT |
age | INT |
message | VARCHAR(100) |
max_dwell_time | DATETIME |
min_dwell_time | DATETIME |
创建调整列顺序的Rollup:
ALTER TABLE table_name ADD ROLLUP rollup_age_first(age, user_id, message, max_dwell_time, min_dwell_time
);
查询优化效果:
-- 该查询会优先选择rollup_age_first
SELECT * FROM table WHERE age=20 AND message LIKE "%error%";
4. Rollup使用说明
4.1 核心特性
- 自动命中:查询时自动选择最优Rollup,无需显式指定
- 独立存储:物理上独立存储,占用额外磁盘空间
- 数据同步:与Base表数据完全同步,无需手动维护
- 聚合方式:继承Base表的聚合方式,不可修改
4.2 命中条件
- 必要条件:查询涉及的所有列都必须存在于Rollup中
- 聚合命中:仅Aggregate/Unique模型支持聚合数据命中
- 索引命中:所有模型都支持前缀索引命中
4.3 限制说明
count(*)
查询无法命中任何Rollup- 创建Rollup会影响导入性能(ETL阶段生成Rollup数据)
- Rollup越多,磁盘空间占用越大
5. 前缀索引机制
5.1 索引原理
- 索引长度:前36个字节(varchar类型最多使用20个字节)
- 存储方式:排序的稀疏索引 + 排序的数据
- 匹配规则:从左到右匹配查询条件中的列
5.2 索引匹配示例
5.3 复杂示例分析
Base表和Rollup结构:
-- Base表
CREATE TABLE test (k1 TINYINT,k2 SMALLINT, k3 INT,k4 BIGINT,k5 DECIMAL(9,3),k6 CHAR(5),k7 DATE,k8 DATETIME,k9 VARCHAR(20),k10 DOUBLE MAX,k11 FLOAT SUM
);-- 多个Rollup
ALTER TABLE test ADD ROLLUP rollup_index1(k9, k1, k2, k3, k4, k5, k6, k7, k8, k10, k11);
ALTER TABLE test ADD ROLLUP rollup_index2(k9, k2, k1, k3, k4, k5, k6, k7, k8, k10, k11);
ALTER TABLE test ADD ROLLUP rollup_index3(k4, k5, k6, k1, k2, k3, k7, k8, k9, k10, k11);
ALTER TABLE test ADD ROLLUP rollup_index4(k4, k6, k5, k1, k2, k3, k7, k8, k9, k10, k11);
前缀索引分布:
- Base: (k1, k2, k3, k4, k5, k6, k7)
- rollup_index1: (k9)
- rollup_index2: (k9)
- rollup_index3: (k4, k5, k6, k1, k2, k3, k7)
- rollup_index4: (k4, k6, k5, k1, k2, k3, k7)
5.4 查询命中分析
示例1:基础条件查询
SELECT * FROM test WHERE k1 = 1 AND k2 > 3;
命中分析:Base表,匹配前缀索引(k1, k2)
示例2:Rollup条件查询
SELECT * FROM test WHERE k4 = 1 AND k5 > 3;
命中分析:rollup_index3,匹配前缀索引(k4, k5)
示例3:Varchar列查询
SELECT * FROM test WHERE k9 IN ("xxx", "yyyy") AND k1 = 10;
命中分析:rollup_index1,匹配前缀索引(k9, k1)
示例4:多Rollup可选
SELECT * FROM test WHERE k4 < 1000 AND k5 = 80 AND k6 >= 10000;
命中分析:rollup_index3或rollup_index4,选择较早创建的
6. 聚合数据命中规则
6.1 命中前提条件
- 查询涉及的所有列都存在于Rollup中
- 如果查询包含Join,必须是Inner Join类型
6.2 聚合函数支持情况
列类型 | SUM | Count Distinct | Min | Max | Approx Count Distinct |
---|---|---|---|---|---|
Key列 | false | true | true | true | true |
Value(Sum) | true | false | false | false | false |
Value(Replace) | false | false | false | false | false |
Value(Min) | false | false | true | false | false |
Value(Max) | false | false | false | true | false |
6.3 聚合Rollup选择策略
6.4 聚合命中示例
表结构:
-- Base表
CREATE TABLE test_rollup (k1 TINYINT, k2 SMALLINT, k3 INT, k4 BIGINT, k5 DECIMAL(9,3),k6 CHAR(5), k7 DATE, k8 DATETIME, k9 VARCHAR(20),k10 DOUBLE MAX, k11 FLOAT SUM
);-- Rollup表
ALTER TABLE test_rollup ADD ROLLUP rollup1(k1, k2, k3, k4, k5, k10, k11);
ALTER TABLE test_rollup ADD ROLLUP rollup2(k1, k2, k3, k10, k11);
查询分析:
SELECT SUM(k11) FROM test_rollup
WHERE k1 = 10 AND k2 > 200 AND k3 in (1,2,3);
命中过程:
- 检查可命中Rollup:rollup1、rollup2都满足
- 前缀索引匹配:两者都匹配(k1, k2, k3),长度相同
- 选择行数最少:rollup2聚合程度更高,选择rollup2
7. 管理和诊断工具
7.1 查看Rollup信息
-- 查看所有Rollup
DESC table_name ALL;-- 查看建表语句(包含Rollup)
SHOW CREATE TABLE table_name;
7.2 执行计划分析
-- 查看查询执行计划
EXPLAIN your_sql;-- 分析Rollup命中情况
EXPLAIN SELECT city, sum(cost) FROM table GROUP BY city;
执行计划关键字段:
rollup
: 显示命中的Rollup名称PREAGGREGATION
: 显示预聚合状态PREDICATES
: 显示应用的查询条件
7.3 Rollup管理命令
-- 创建Rollup
ALTER TABLE table_name ADD ROLLUP rollup_name(column_list);-- 删除Rollup
ALTER TABLE table_name DROP ROLLUP rollup_name;-- 查看Rollup创建进度
SHOW ALTER TABLE ROLLUP;
8. 最佳实践
8.1 Rollup设计原则
- 高频查询优先:为最频繁的查询模式创建Rollup
- 数据聚合度:选择聚合程度高的列组合
- 存储成本:平衡查询性能与存储开销
- 列顺序优化:将过滤条件频繁的列放在前面
8.2 常见场景建议
8.2.1 报表分析场景
-- 为日报表创建Rollup
ALTER TABLE sales ADD ROLLUP rpt_daily(event_date, product_category, region, total_sales SUM, total_orders SUM
);-- 为月报表创建Rollup
ALTER TABLE sales ADD ROLLUP rpt_monthly(date_trunc('month', event_date), product_category,total_sales SUM, total_orders SUM
);
8.2.2 用户行为分析
-- 用户维度聚合
ALTER TABLE user_behavior ADD ROLLUP rollup_user(user_id, last_visit_date REPLACE, total_clicks SUM, max_duration MAX
);-- 页面维度聚合
ALTER TABLE user_behavior ADD ROLLUP rollup_page(page_id, total_views SUM, avg_duration AVG, bounce_rate MIN
);
8.3 性能监控
-- 监控Rollup使用情况
SHOW PROC "/dbs/db_id/table_id/indices";-- 分析查询模式
EXPLAIN ANALYZE your_sql;-- 监控存储开销
SHOW DATA;
9. 注意事项
9.1 设计注意事项
- 避免创建过多Rollup影响导入性能
- 定期评估Rollup的使用效果
- 考虑数据更新频率对Rollup维护的影响
9.2 使用限制
- 无法显式指定查询某个Rollup
- 某些查询类型无法命中Rollup(如count(*))
- Rollup一旦创建,修改需要重建
9.3 故障排查
- 使用EXPLAIN检查Rollup命中情况
- 监控Rollup构建进度和状态
- 关注存储空间使用情况