公司前期做智能營銷,其中有一個基於標簽全選人群的操作,讓廣告主能看到在當前標簽條件下,能夠全選多少人群,從而做到最大投放收益效果
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 )
但是上述方式有個比較大的問題就是,多維交叉出來的數據太多了,可能百億條.放入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 )
細節點就是將字段類型從字符串變成了數組.這樣做的好處就是原本百億條數據,經過數據數組處理后,最終不到一億條,同時利用clickhouse的數組函數:
原本需要最少倆小時才能出試算結果,經過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)
獲取人群試算結果 |競品ID |包類型 |人群試算結果 |99999 |99999 |人群包整體 |99999 |1 |本品關注包 |99999 |2 |競品關注包整體 |某競品ID |99999 |某競品包總人數 |某競品ID |99999 |某競品包總人數 |99999 |3 |自選關注寶
下一篇准備寫一寫,畫像數據,基於bitmap處理后的優化。性能提升非常多....