簡介:
Doris(原百度 Palo)是一款基于大規(guī)模并行處理技術(shù)的分布式 SQL 數(shù)據(jù)庫,由百度在 2017 年開源情屹,2018 年 8 月進(jìn)入Apache 孵化器敌厘。
定位:
- MPP 架構(gòu)的關(guān)系型分析數(shù)據(jù)庫
- PB 級(jí)別大數(shù)據(jù)集糠亩,秒級(jí) / 毫秒級(jí)查詢
- 主要用于多維分析和報(bào)表查詢
-
2018 年進(jìn)入 Apache 孵化器
架構(gòu):
Doris 的架構(gòu)很簡潔,只設(shè) FE(Frontend)鲁驶、BE(Backend) 兩種角色鉴裹、兩個(gè)進(jìn)程,不依賴于外部組件钥弯,方便部署和運(yùn)維径荔。
- 以數(shù)據(jù)存儲(chǔ)的角度觀之,F(xiàn)E 存儲(chǔ)脆霎、維護(hù)集群元數(shù)據(jù)总处;BE 存儲(chǔ)物理數(shù)據(jù)。
- 以查詢處理的角度觀之, FE 節(jié)點(diǎn)接收睛蛛、解析查詢請(qǐng)求鹦马,規(guī)劃查詢計(jì)劃,調(diào)度查詢執(zhí)行忆肾,返回查詢結(jié)果荸频;BE 節(jié)點(diǎn)依據(jù) FE 生成的物理計(jì)劃,分布式地執(zhí)行查詢客冈。
實(shí)操過程:
1.機(jī)器:
三臺(tái)虛擬機(jī)16核试溯,64G,300G硬盤郊酒,
三臺(tái)部署B(yǎng)E,一臺(tái)部署FE,
- 高可用:
當(dāng)部署多個(gè) FE 節(jié)點(diǎn)時(shí)键袱,用戶可以在多個(gè) FE 之上部署負(fù)載均衡層來實(shí)現(xiàn) Doris 的高可用
3.數(shù)據(jù)導(dǎo)入:
提供了5種不同的導(dǎo)入方式燎窘。每種導(dǎo)入方式支持不同的數(shù)據(jù)源,存在不同的使用方式(異步蹄咖,同步)褐健。所有導(dǎo)入方式都支持 csv 數(shù)據(jù)格式。其中Broker load 還支持 parquet 和 orc 數(shù)據(jù)格式,
Broker load方式導(dǎo)入測試表:通過show load命令查看導(dǎo)入進(jìn)度
事實(shí)表:cupid_test.dws_test4 571.3 G
維度表:cupid_test.doris_dim_test 140.7M
導(dǎo)入后數(shù)據(jù):
cupid_test.dws_test4 540G
cupid_test.doris_dim_test 98.8M
使用導(dǎo)入限制:每次導(dǎo)入文件大小不超過3G,可通過參數(shù)調(diào)整
4.分區(qū)與分桶:
Doris 支持兩級(jí)分區(qū)存儲(chǔ), 第一層為 RANGE 分區(qū)(partition), 第二層為 HASH 分桶(bucket)
RANGE分區(qū):用于將數(shù)據(jù)劃分成不同區(qū)間, 邏輯上可以理解為將原始表劃分成了多個(gè)子表蚜迅。業(yè)務(wù)上舵匾,多數(shù)用戶會(huì)選擇采用按時(shí)間進(jìn)行partition, 讓時(shí)間進(jìn)行partition有以下好處:
- 可區(qū)分冷熱數(shù)據(jù)
- 可用上Doris分級(jí)存儲(chǔ)(SSD + SATA)的功能
- 按分區(qū)刪除數(shù)據(jù)時(shí),更加迅速
HASH 分桶:根據(jù)hash值將數(shù)據(jù)劃分成不同的 bucket谁不。
- 建議采用區(qū)分度大的列做分桶, 避免出現(xiàn)數(shù)據(jù)傾斜
- 為方便數(shù)據(jù)恢復(fù), 建議單個(gè) bucket 的 size 不要太大, 保持在 10GB 以內(nèi), 所以建表或增加 partition 時(shí)請(qǐng)合理考慮 bucket 數(shù)目, 其中不同 partition 可指定不同的 buckets 數(shù)坐梯。
5.建表與數(shù)據(jù)模型:
建表注意點(diǎn):
- 需將分區(qū)字段排第一個(gè)字段
- 維度排在前面,指標(biāo)排在后面
數(shù)據(jù)模型:AGGREGATE KEY, UNIQUE KEY, DUPLICATE KEY
AGGREGATE KEY相同時(shí)刹帕,新舊記錄進(jìn)行聚合吵血,目前支持的聚合函數(shù)有SUM, MIN, MAX, REPLACE,AGGREGATE KEY模型可以提前聚合數(shù)據(jù), 適合報(bào)表和多維分析業(yè)務(wù)
UNIQUE KEY 相同時(shí)偷溺,新記錄覆蓋舊記錄蹋辅。目前 UNIQUE KEY 實(shí)現(xiàn)上和 AGGREGATE KEY 的 REPLACE 聚合方法一樣,二者本質(zhì)上相同挫掏。適用于有更新需求的分析業(yè)務(wù)侦另。
DUPLICATE KEY,只指定排序列尉共,相同的行不會(huì)合并褒傅。適用于數(shù)據(jù)無需提前聚合的分析業(yè)務(wù)
建表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 中,我們將用戶通過建表語句創(chuàng)建出來的表成為 Base 表(Base Table)爸邢。Base 表中保存著按用戶建表語句指定的方式存儲(chǔ)的基礎(chǔ)數(shù)據(jù)樊卓。在 Base 表之上,我們可以創(chuàng)建任意多個(gè) ROLLUP 表杠河。這些 ROLLUP 的數(shù)據(jù)是基于 Base 表產(chǎn)生的碌尔,并且在物理上是獨(dú)立存儲(chǔ)的。ROLLUP 表的基本作用券敌,在于在 Base 表的基礎(chǔ)上唾戚,獲得更粗粒度的聚合數(shù)據(jù)。
在查詢時(shí)會(huì)根據(jù)索引路由查詢base表還是rollup表
前綴索引:Doris 不支持在任意列上創(chuàng)建索引待诅,將一行數(shù)據(jù)的前 36 個(gè)字節(jié) 作為這行數(shù)據(jù)的前綴索引叹坦。當(dāng)遇到 VARCHAR 類型時(shí),前綴索引會(huì)直接截?cái)?/p>
DEMO:
創(chuàng)建rollup:
ALTER TABLE dws_test4 add ROLLUP rollup_order_plan(order_plan_id,cnt,price);
查詢命中情況:
- Broadcast/Shuffle Join
Broadcast join,是將小表進(jìn)行條件過濾后卑雁,將其廣播到大表所在的各個(gè)節(jié)點(diǎn)上募书,形成一個(gè)內(nèi)存 Hash 表,然后流式讀出大表的數(shù)據(jù)進(jìn)行Hash Join测蹲。但是如果當(dāng)小表過濾后的數(shù)據(jù)量無法放入內(nèi)存的話莹捡,此時(shí) Join 將無法完成,通常的報(bào)錯(cuò)應(yīng)該是首先造成內(nèi)存超限扣甲。
Shuffle Join 的方式篮赢,也被稱作 Partitioned Join。即將小表和大表都按照 Join 的 key 進(jìn)行 Hash,然后進(jìn)行分布式的Join启泣。這個(gè)對(duì)內(nèi)存的消耗就會(huì)分?jǐn)偟郊旱乃杏?jì)算節(jié)點(diǎn)上
默認(rèn)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