互聯網用戶畫像,精準營銷,數倉有妙招
- 2022 年 5 月 11 日
- 筆記
- GaussDB(DWS), Roaringbitmap, 位圖, 華為雲新鮮技術分享, 用戶畫像, 精準營銷
摘要:通過GaussDB(DWS)的Roaringbitmap功能,實現用戶畫像,精準營銷功能。
本文分享自華為雲社區《互聯網用戶畫像,精準營銷,GaussDB(DWS)來支招》,作者: fudgefactor。
目前在互聯網、教育、遊戲等行業都有實時精準營銷的需求。通過系統生成用戶畫像,在營銷時通過條件組合篩選用戶,快速提取目標群體。例如:
- 在電商行業中,商家在進行營銷活動前,需要根據活動的目的,圈選一批滿足特定特徵的目標用戶群體進行廣告推送。
- 在教育行業中,需要根據學生不同的特徵,推送有針對性的練習題目,幫助學生查漏補缺。
- 在搜索、視頻、門戶網站中,根據用戶關注的熱點,推送不同的內容。
這些業務場景都有一些共同的特點:
- 數據量龐大,運算量極大。
- 用戶規模龐大,標籤多,字段多,佔用存儲空間也多。
- 圈選的特徵條件多樣化,很難找到固定索引,如果每個字段一個索引,存儲空間又會暴增。
- 性能要求高,因為實時營銷要求秒級響應。
- 數據更新時效要求高,用戶畫像幾乎要求實時更新。
針對上述業務場景特點,GaussDB(DWS)的roaringbitmap可以高效生成、壓縮、解析位圖數據,支持最常見的位圖聚合操作(與、或、非、異或),滿足用戶在億級以上用戶、千萬級標籤的大數據量下實時精準營銷、快速圈選用戶的需求。
下面先通過兩個示例來理解Roaringbitmap在用戶畫像場景中的使用方法。
示例一:
假設有一張用戶瀏覽網頁的流水信息表userinfo,表中的字段如下:
CREATE TABLE userinfo (userid int, age int, gender text, salary int, hobby text )with (orientation=column);
userinfo表中的數據會隨着用戶信息的變化不斷增長,同時,如果用戶有多個”愛好”(hobby),那麼就有多條記錄對應同一個userid。
假設要篩選出所有「收入大於10000元的男性,年齡大於30歲,愛好釣魚」的群體,向這些目標群體推送特定的消息。
傳統的方法是直接在原表上執行查詢,語句如下:
select distinct userid from userinfo where salary > 10000 and age > 30 and gender ='m' and hobby ='fishing';
當userinfo表的數據量不大的時候,可以通過在salary, age, gender,hobby列上建立索引來滿足需求。但是如果userinfo表的數據量非常大,同時一張表的標籤數非常多(比如有100個屬性,需要對應有100個列)的時候,上述語句就不能滿足訴求,因為如下原因:
- 由於不確定會按照那些屬性做過濾,需要創建的索引會非常多。
- 求distinct的性能比較差。
這種場景下使用roaringbitmap就會有比較好的效果。
- 新建一張Roaringbitmap表:
CREATE TABLE userinfoset ( age int, gender text, salary int, hobby text, userset roaringbitmap, PRIMARY KEY(age,gender,salary,hobby) )with (orientation=column);
2. 所有userinfo表中的數據要通過標籤列聚合到userinfoset表中。可以採用對全量數據進行聚合的方法(如下命令所示)。
insert into userinfoset us select age, gender, salary, hobby, rb_build_agg(userid) from userinfo group by age, gender, salary, hobby;
3. 直接查詢userinfoset表獲得用戶篩選信息。
select rb_iterate(rb_or_agg(userset)) from userinfoset where salary > 10000 and age > 30 and gender ='m' and hobby ='fishing';
數據進行聚合後的userinfoset的數據量相比源表小了很多,基表scan的性能會快很多,同時基於Roaringbitmap的優勢,計算rb_or_agg和rb_iterate的性能也很好,相比傳統的方法,性能明顯提升。
示例二:
由於DWS規格的限制,每張表最大可以有1600列,如果描述用戶的屬性有10000個,我們無法通過創建一個有10000列的表來實現這個方案,那麼示例一中的方案就不再有效了。
為此,我們可以這樣設計我們的表結構:
create table userinfoset ( tag_value_id int, userset roaringbitmap )with(orientation=column);
其中tag_value_id表示屬性值對應的id,比如,性別這一屬性,有」男「,」女「兩個值,我們可以把它編碼為1,2;學歷這個屬性的取值是」專科「,」本科「,」碩士「,「博士」,那麼分別編碼為3,4,5,6,等等。將不同的屬性值編碼為不同的id值。
userset列表示的是滿足tag_value_id所對應屬性值的用戶id的集合。比如tag_value_id=1這條記錄對應的userset就是所有性別為男的用戶的集合。
數據加工:
這個表的數據一般是需要通過加工得到的,假設原始數據的表結構如下(一共有10張表):
create table origin_1 ( userid int, tag_value_id1 int, tag_value_id2 int, tag_value_id3 int, ... tag_value_id998 int, tag_value_id999 int, tag_value_id1000 int )with(orientation=column); ... create table origin_10 ( userid int, tag_value_id9001 int, tag_value_id9002 int, tag_value_id9003 int, ... tag_value_id9998 int, tag_value_id9999 int, tag_value_id10000 int )with(orientation=column);
我們可以通過類似以下的語句將數據加工到目標表中:
insert into userinfoset select tag_value_id1, rb_build_agg(userid) origin_1 from origin group by tag_value_id1; ... insert into userinfoset select tag_value_id10000, rb_build_agg(userid) origin_10 from origin group by tag_value_id10000;
查詢:
假設需要圈選性別為男,學歷為本科的用戶的的個數有哪些,可以用以下語句實現:
select rb_or_cardinality_agg(userset) from userinfoset where tag_value_id in (1,4);
如果用戶要圈選的人群有更多的特徵,將對應的tag_value_id加入到in子句中即可。
如果想要知道這些用戶的具體的userid,可以通過如下函數實現:
select rb_iterate(rb_or_cardinality_agg(userset)) from userinfoset where tag_value_id in (1,4);
可以通過查詢產品手冊實現更加多樣化的人群圈選策略。