1. 背景
Apache Doris 原有的BitMap函數雖然比較通用, 但在億級别的BitMap大基數并交計算性能較差,主要是由以下兩個原因造成的:
- 當BitMap的基數過大,大小超過1GB時,網絡或者磁盤的處理時間較長
- BE節點掃描完資料後傳輸到一個FE節點進行并交計算,給該FE節點帶來壓力,成為處理瓶頸
解決方案:将bitmap列的值按照範圍劃分,不同範圍的值存儲在不同的bucket上,確定在不同bucket的bitmap值是正交的。在查詢的時候,先對不同bucket的bitmap值完成聚合計算,上層的FE節點隻需合并聚合過的資料并輸出即可。如此會極大的改善計算效率,和解決FE節點成為計算瓶頸的問題。
2. 使用指南
增加一列hid, 表示range的範圍,作為hash分桶列
如:
CREATE TABLE ssb.`lineorder_bitmap` (
`lo_shipmode` varchar(50) NULL COMMENT "user tag",
`hid` smallint(6) NULL COMMENT "Bucket ID",
`lo_orderkey` bitmap BITMAP_UNION NULL COMMENT ""
) ENGINE=OLAP
AGGREGATE KEY(`lo_shipmode`, `hid`)
COMMENT "OLAP"
DISTRIBUTED BY HASH(`hid`) BUCKETS 3
PROPERTIES (
"replication_allocation" = "tag.location.default: 1",
"in_memory" = "false",
"storage_format" = "V2",
"disable_auto_compaction" = "false"
);
3. 實際查詢效果
3.1 分組去重
select
lo_shipmode
,orthogonal_bitmap_union_count(lo_orderkey) cnt
from ssb.`lineorder_bitmap`
group by lo_shipmode

查詢結果與上一篇使用COUNT(DISTINCT)的結果一緻。
耗時對比:
COUNT(DISTINCT) : 12秒
bitmap_count(bitmap_union(to_bitmap(lo_orderkey))):6秒
本文使用的orthogonal_bitmap_union_count(lo_orderkey):219毫秒
計算性能得到了極大的提升。
3.2 全量去重
COUNT(DISTINCT) : 2.15秒
bitmap_count(bitmap_union(to_bitmap(lo_orderkey))):3.26秒
本文使用的orthogonal_bitmap_union_count(lo_orderkey):141毫秒
同樣,計算性能也是得到了極大的提升。