基於clickhouse實現標簽圈人(人群試算)的優化


 

 

公司前期做智能營銷,其中有一個基於標簽全選人群的操作,讓廣告主能看到在當前標簽條件下,能夠全選多少人群,從而做到最大投放收益效果

 

 

1、產品背景

公司要實現一套基於標簽的投放平台;主要想基於廣告主給定的標簽來圈定人群。然后在將廣告投放出去,達到精准投放的效果;

2、頁面產品

頁面大概漲這個樣子:

 

 3、數據量

3.1、每天日活的用戶大概300萬左右,假如90天90秒的活用用戶量為600萬 

3.2、產品數量大概在3000個

3.3、多個標簽維度,比如有50個標簽維度

3.4、地域維度

綜上所屬,假如90天90秒的活躍用戶量為600萬,在標簽維度和產品數量等交叉后出現的結果總量不會小於百億......

4、項目前期處理方式

前期處理的調用鏈非常不合理,大概的意思是:

 

 

 從上圖能看出調用鏈非常的長,而且服務端和數據端耦合性特別高,是一種非常不合理的設計方案;

而且上述的處理方式,廣告主想要獲取人群的試算結果,需要等若干個小時,用戶體驗也特別不好;

5、基於ck進行優化處理

為什么我們這里要使用ck?

上面簡單介紹過每天的日活,以及各種維度標簽,當他們進行多維交叉處理后,產生的數據量非常驚人.即便是hive也是很吃力的,而且處理響應速度慢,用戶體驗差;

那么為什么使用ck后,就可以優化處理,用戶體驗變好?上面提到過,有可能多維交叉處理后,出現百億條數據,即便是ck,這么多行數據,也是吃力的;

因此,我們使用了ck的一些數組和數組函數.將多條數據進行壓縮處理;

比如:

正常在hive,當前表的schema表現形式是:

 1 CREATE TABLE hive的表
 2 (
 3     `dt` String DEFAULT '9999-01-11' COMMENT '時間',
 4     `dvid` String DEFAULT '-9999' COMMENT '設備ID',
 5     `car_model_id` String DEFAULT '-9999' COMMENT '本品ID',
 6     `car_model_cp_id` String DEFAULT '-9999' COMMENT '競品ID',
 7     `package_type` String DEFAULT '-9999' COMMENT '人群包類型',
 8     `age_range` String DEFAULT '-9999' COMMENT '年齡范圍',
 9     `city_level_id` String DEFAULT '-9999' COMMENT '城市級別',
10     `pricerange_id` String DEFAULT '-9999' COMMENT '價格偏好',
11     `car_level2_id` String DEFAULT '-9999' COMMENT '級別偏好',
12     `carbrand_id` String DEFAULT '-9999' COMMENT '品牌偏好',
13     `province_id` String DEFAULT '-9999' COMMENT '省份偏好',
14     `city_id` String DEFAULT '-9999' COMMENT '城市偏好',
15     `is_yest_dau` Int16 DEFAULT -9999 COMMENT '是否昨日日活(0不是 1是)',
16     `is_yest_recom_dau` Int16 DEFAULT -9999 COMMENT '是否昨日首頁推薦日活(0不是 1是)',
17     `create_date` Date DEFAULT now() COMMENT '創建時間'
18 )
View Code

但是上述方式有個比較大的問題就是,多維交叉出來的數據太多了,可能百億條.放入ck去做處理,各種維度求和,也是非常慢的;

所以最終我們將表結構處理成:

 1 CREATE TABLE ck的表
 2 (
 3     `dt` String DEFAULT '9999-01-11' COMMENT '時間',
 4     `dvid` String DEFAULT '-9999' COMMENT '設備ID',
 5     `car_model_id` Array(Int64) DEFAULT [-9999] COMMENT '本品ID',
 6     `car_model_cp_id` Array(Int64) DEFAULT [-9999] COMMENT '競品ID',
 7     `package_type` Array(Int64) DEFAULT [-9999] COMMENT '人群包類型',
 8     `age_range` Array(Int64) DEFAULT [-9999] COMMENT '年齡范圍',
 9     `city_level_id` Array(Int64) DEFAULT [-9999] COMMENT '城市級別',
10     `pricerange_id` Array(Int64) DEFAULT [-9999] COMMENT '價格偏好',
11     `car_level2_id` String DEFAULT '-9999' COMMENT '級別偏好',
12     `carbrand_id` Array(Int64) DEFAULT [-9999] COMMENT '品牌偏好',
13     `province_id` Array(Int64) DEFAULT [-9999] COMMENT '省份偏好',
14     `city_id` Array(Int64) DEFAULT [-9999] COMMENT '城市偏好',
15     `is_yest_dau` Int16 DEFAULT -9999 COMMENT '是否昨日日活(0不是 1是)',
16     `is_yest_recom_dau` Int16 DEFAULT -9999 COMMENT '是否昨日首頁推薦日活(0不是 1是)',
17     `create_date` Date DEFAULT now() COMMENT '創建時間'
18 )
View Code

細節點就是將字段類型從字符串變成了數組.這樣做的好處就是原本百億條數據,經過數據數組處理后,最終不到一億條,同時利用clickhouse的數組函數:

hasAny

原本需要最少倆小時才能出試算結果,經過ck優化后,只需要2~10秒鍾(跟品牌關注度有關)

最終出來的sql大概長這個樣子:

 1 select cp_id , type ,count(1) as totalNum , sum(is_yest_dau) as is_yest_dau , sum(is_yest_recom_dau ) as is_yest_recom_dau 
 2 from  
 3 (
 4 select dvid,is_yest_dau,is_yest_recom_dau ,99999 as cp_id,1 as type   from app_index_renqun_shisuan_day_v2_all 
 5 where hasAny(province_id, [1502]) > 0 and hasAny(car_model_id,[5394]) > 0 and hasAny(package_type,[1]) > 0
 6 union all
 7 select dvid,is_yest_dau,is_yest_recom_dau ,99999 as cp_id,2 as type  from app_index_renqun_shisuan_day_v2_all 
 8 where hasAny(province_id,[1502]) > 0 and hasAny(car_model_cp_id,[4597, 5301]) > 0 and hasAny(package_type,[2]) > 0
 9 union all
10 select dvid,is_yest_dau,is_yest_recom_dau ,99999 as cp_id,3 as type  from app_index_renqun_shisuan_day_v2_all 
11 where hasAny(province_id, [1502]) > 0 and hasAny(package_type,[3]) > 0
12 
13 union all
14 select dvid , is_yest_dau , is_yest_recom_dau , arrayJoin(car_model_cp_id) as cp_id , 99999 as type from
15 (
16 select dvid,is_yest_dau,is_yest_recom_dau ,car_model_cp_id  from app_index_renqun_shisuan_day_v2_all 
17 where 
18 (hasAny(province_id,[1502]) > 0 and hasAny(car_model_cp_id,[4597, 5301]) > 0 and hasAny(package_type,[2]) > 0)
19 )
20 where has([4597, 5301] , cp_id) >0
21 ) group by cp_id,type 
22 
23 union all
24 select  99999 , 99999 ,count(1) totalNum ,sum(is_yest_dau) as is_yest_dau ,sum(is_yest_recom_dau ) as is_yest_recom_dau from app_index_renqun_shisuan_day_v2_all 
25 where 
26 (hasAny(province_id, [1502]) > 0 and hasAny(car_model_id,[5394]) > 0 and hasAny(package_type,[1]) > 0)
27 or
28 (hasAny(province_id,[1502]) > 0 and hasAny(car_model_cp_id,[4597, 5301]) > 0 and hasAny(package_type,[2]) > 0)
29 or
30 (hasAny(province_id, [1502]) > 0 and hasAny(package_type,[3]) > 0)
View Code

 

獲取人群試算結果
|競品ID    |包類型   |人群試算結果
|99999    |99999   |人群包整體
|99999    |1       |本品關注包
|99999    |2       |競品關注包整體
|某競品ID    |99999   |某競品包總人數
|某競品ID    |99999   |某競品包總人數
|99999     |3       |自選關注寶

 

下一篇准備寫一寫,畫像數據,基於bitmap處理后的優化。性能提升非常多....


免責聲明!

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



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