简介:
Doris(原百度 Palo)是一款基于大规模并行处理技术的分布式 SQL 数据库,由百度在 2017 年开源,2018 年 8 月进入Apache 孵化器。
定位:
- MPP 架构的关系型分析数据库
- PB 级别大数据集,秒级 / 毫秒级查询
- 主要用于多维分析和报表查询
-
2018 年进入 Apache 孵化器
架构:
Doris 的架构很简洁,只设 FE(Frontend)、BE(Backend) 两种角色、两个进程,不依赖于外部组件,方便部署和运维。
- 以数据存储的角度观之,FE 存储、维护集群元数据;BE 存储物理数据。
- 以查询处理的角度观之, FE 节点接收、解析查询请求,规划查询计划,调度查询执行,返回查询结果;BE 节点依据 FE 生成的物理计划,分布式地执行查询。
实操过程:
1.机器:
三台虚拟机16核,64G,300G硬盘,
三台部署BE,一台部署FE,
- 高可用:
当部署多个 FE 节点时,用户可以在多个 FE 之上部署负载均衡层来实现 Doris 的高可用
3.数据导入:
提供了5种不同的导入方式。每种导入方式支持不同的数据源,存在不同的使用方式(异步,同步)。所有导入方式都支持 csv 数据格式。其中Broker load 还支持 parquet 和 orc 数据格式,
Broker load方式导入测试表:通过show load命令查看导入进度
事实表:cupid_test.dws_test4 571.3 G
维度表:cupid_test.doris_dim_test 140.7M
导入后数据:
cupid_test.dws_test4 540G
cupid_test.doris_dim_test 98.8M
使用导入限制:每次导入文件大小不超过3G,可通过参数调整
4.分区与分桶:
Doris 支持两级分区存储, 第一层为 RANGE 分区(partition), 第二层为 HASH 分桶(bucket)
RANGE分区:用于将数据划分成不同区间, 逻辑上可以理解为将原始表划分成了多个子表。业务上,多数用户会选择采用按时间进行partition, 让时间进行partition有以下好处:
- 可区分冷热数据
- 可用上Doris分级存储(SSD + SATA)的功能
- 按分区删除数据时,更加迅速
HASH 分桶:根据hash值将数据划分成不同的 bucket。
- 建议采用区分度大的列做分桶, 避免出现数据倾斜
- 为方便数据恢复, 建议单个 bucket 的 size 不要太大, 保持在 10GB 以内, 所以建表或增加 partition 时请合理考虑 bucket 数目, 其中不同 partition 可指定不同的 buckets 数。
5.建表与数据模型:
建表注意点:
- 需将分区字段排第一个字段
- 维度排在前面,指标排在后面
数据模型:AGGREGATE KEY, UNIQUE KEY, DUPLICATE KEY
AGGREGATE KEY相同时,新旧记录进行聚合,目前支持的聚合函数有SUM, MIN, MAX, REPLACE,AGGREGATE KEY模型可以提前聚合数据, 适合报表和多维分析业务
UNIQUE KEY 相同时,新记录覆盖旧记录。目前 UNIQUE KEY 实现上和 AGGREGATE KEY 的 REPLACE 聚合方法一样,二者本质上相同。适用于有更新需求的分析业务。
DUPLICATE KEY,只指定排序列,相同的行不会合并。适用于数据无需提前聚合的分析业务
建表Demo:
CREATE TABLE site_visit
(
dt date,
siteid INT,
city SMALLINT,
username VARCHAR(32),
pv BIGINT SUM DEFAULT '0'
)
AGGREGATE KEY(dt,siteid,city, username)
PARTITION BY RANGE ( dt ) ( PARTITION p20200501 VALUES LESS THAN ( '2020-05-01' ) )
DISTRIBUTED BY HASH(siteid) BUCKETS 10;
- 物理视图(rollup)与索引
在 Doris 中,我们将用户通过建表语句创建出来的表成为 Base 表(Base Table)。Base 表中保存着按用户建表语句指定的方式存储的基础数据。在 Base 表之上,我们可以创建任意多个 ROLLUP 表。这些 ROLLUP 的数据是基于 Base 表产生的,并且在物理上是独立存储的。ROLLUP 表的基本作用,在于在 Base 表的基础上,获得更粗粒度的聚合数据。
在查询时会根据索引路由查询base表还是rollup表
前缀索引:Doris 不支持在任意列上创建索引,将一行数据的前 36 个字节 作为这行数据的前缀索引。当遇到 VARCHAR 类型时,前缀索引会直接截断
DEMO:
创建rollup:
ALTER TABLE dws_test4 add ROLLUP rollup_order_plan(order_plan_id,cnt,price);
查询命中情况:
- Broadcast/Shuffle Join
Broadcast join,是将小表进行条件过滤后,将其广播到大表所在的各个节点上,形成一个内存 Hash 表,然后流式读出大表的数据进行Hash Join。但是如果当小表过滤后的数据量无法放入内存的话,此时 Join 将无法完成,通常的报错应该是首先造成内存超限。
Shuffle Join 的方式,也被称作 Partitioned Join。即将小表和大表都按照 Join 的 key 进行 Hash,然后进行分布式的Join。这个对内存的消耗就会分摊到集群的所有计算节点上
默认Broadcast:
select sum(aa.price)
from dws_test4 aa
join dim_da bb
on aa.creative_id = bb.creative_id
and bb.day='2020-04-01'
where aa.creative_id = 64001348383
and aa.day='2020-04-01'
;
13.69 sec
select sum(aa.price)
from dws_test4 aa
join [shuffle] dim_test bb
on aa.creative_id = bb.creative_id
and bb.day='2020-04-01'
where aa.creative_id = 64001348383
and aa.day='2020-04-01'
;
11.34 sec
select bb.order_id,sum(aa.price)
from dws_test4 aa
join [shuffle] dim_test bb
on aa.creative_id = bb.creative_id
and bb.day='2020-04-01'
where aa.day='2020-04-01'
group by bb.order_id
;
2 min 8.74 sec