互聯網用戶畫像,精準營銷,數倉有妙招

摘要:通過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就會有比較好的效果。

  1. 新建一張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);

可以通過查詢產品手冊實現更加多樣化的人群圈選策略。

 

點擊關注,第一時間了解華為雲新鮮技術~