基於clickhouse的Bitmap實現任意時間段的去重求基數操作


 

 

1、什么是bitmap

bitmap的介紹:https://www.cnblogs.com/cjsblog/p/11613708.html

2、Clickhouse的RoaringBitmap介紹

https://blog.csdn.net/yizishou/article/details/78342499

3、基於bitmap實現業務需求

我們的需求場景是:任意時間段, 求關注的人群基數(去重)

如果使用傳統數倉按天分區做法,成本會非常高,而且無法做到在線查詢出結果的

簡單解釋下:

2021-01-01這一天  關注的iphone12的人是 : [張三、王五、趙六]

2021-01-02這一天 關注的iphone12的人是 : [王五、趙六、陳七]

求這兩天關注過iphone12的人數量:

[張三、王五、趙六]
or
[王五、趙六、陳七]
然后去重,得到:
[[張三、王五、趙六、陳七]

 

求2021-01-01到2021-01-02的留存人數:

[張三、王五、趙六]
     and
[王五、趙六、陳七]
相交得到:
[王五、趙六]

 

求2021-01-02 相比 2021-01-01的新增人數

[王五、趙六、陳七]
     andNot
[張三、王五、趙六]
在2021-01-02出現過,但沒有在2021-01-01出現過的人
[陳七]

 

以上的操作如果要通過Clickhouse實現,需要如下幾步:

第一步:在clickhouse形成滿足需求的寬表

第二步:基於寬表實現bitmap表

第三步:實現需求查詢的sql

3.1、實現業務寬表

我們實現寬表的方式是:Hive加工處理,得到業務寬表,然后經過Datax將數據同步到Clickhouse里面

比如,按照上面的邏輯,實現的寬表就是(clickhouse的表):

{
   dt string 時間
   brand  品牌  手機品牌
   phone_model  手機型號
   device_id String  設備號      
}

【注意】:這一步后續是可優化的,要結合bitmap的特性和clickhouse的表引擎來優化

3.2、基於寬表實現bitmap表

clickhouse的bitmap函數頁面:https://clickhouse.com/docs/zh/sql-reference/functions/bitmap-functions/

簡單分析下需求,我們要取品牌、型號、天維度下的人群基數

那么Clickhouse的bitmap表可以做成如下結構:

{
     dt  LowCardinality(String)   時間
     dim_type  LowCardinality(String)  維度類型(1:品牌維度、2:手機型號維度)
     dim_value LowCardinality(String) 每個dim_type維度下對應的品牌或者手機型號值
     bitmap_dvid  AggregateFunction(groupBitmap, UInt32) 明細
}

然后通過jdbc或者sparkSQL,實現如下操作,向clickhouse的bitmap表插入數據:

1):插入數據前,刪除分區

alter table bitmap的表 on cluster default_cluster drop partition 時間分區

2):分別插入不同維度的bitmap

插入品牌維度:
INSERT INTO bitmap表 select dt , 1 , brand , groupBitmapState(toUInt32(dvid)) as dvid from 寬表 where dt = 日期 
group by brand

插入型號維度
INSERT INTO bitmap表 select dt , 2 , phone_model , groupBitmapState(toUInt32(dvid)) as dvid from 寬表 where dt = 日期 
group by phone_model

3):查詢新增、留存等

查詢iphone12品牌在當前周期(2021-07-01~2021-09-29)相比上周期(2021-05-01 ~ 2021-06-30)的留存人數
select bitmapCardinality(
    bitmapAnd(
       select groupBitmapOrState(devid_bmp) from(
          select devid_bmp from bitmap表 where dt >= '2021-07-01' and dt <= '2021-09-29' and dim_type = 1 and dim_value = 'iphone12'
       ) , -- 當期周期關注過iphone12的人
       select groupBitmapOrState(devid_bmp) from(
          select devid_bmp from bitmap表 where dt >= '2021-05-01' and dt <= '2021-06-30' and dim_type = 1 and dim_value = 'iphone12'
       )  -- 上周期關注過iphone12的人
    )
)

經過測驗:一個月的人群數量大約是:1億

通過bitmap查詢留存,一個月的情況,不到2s

4、優化bitmap在clickhouse上的使用

4.1、引擎上的選擇

首先是引擎上的選擇,實際壓測,發現兩種引擎在bitmap場景下效率最高,分別是:

1、MergeTree

2、ReplicatedMergeTree

其中使用MergeTree性能會更好

 

4.2、縮減bitmap的大小

我們的設備明細一般是64位的,經過hash散列后,占用的bitmap空間其實是非常大的

所以我們對所有的設備明細維護了一套數字(其實就是hive的row_number)

這樣bitmao大大縮減,極大提升查詢速度,減小了每次查詢使用的CPU和內存

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM