根据画像标签的需求场景,我们常常将画像存储分为两部份,分别是:
- 画像基本信息的存储
- 用户画像人群的筛选需求的存储
常见画像标签存储方式:
- 根据类目创建宽表,或者根据更新的频率创建宽表
- 创建竖表-每个用户+每个标签=一条记录
- 竖表+横表=》分开计算,定时聚合
- ES 标签对象存储,rowKey为user_id,HBASE存储用户明细,通过user_id关联
- 倒排表,标签-》多个用户Id,bitmap方案
一、根据类目创建宽表,或者根据更新的频率创建宽表
1. 这是最容易想到的方式,同时也是最直观的方式,比如有基本信息表,兴趣爱好表
| user_id |
姓名 |
性别 |
| 1 |
老五 |
男 |
| 2 |
老四 |
女 |
| user_id |
购房意向 |
意向户型 |
| 1 |
高 |
50-100m |
| 2 |
低 |
200-300m |
优点:
- 够直观,简单,结构清晰,数据量可控
缺点:
- 标签的增加需要修改表结构 — 只要能确定标签的范围,那可以省略这个问题
- 存储一定冗余,会存在有些字段无值的场景
- 计算不友好,在同一表中的各标签值计算时间和规则是不相同的,这些标签值的来源常常来源于各实时计算,或离线计算程序,或者是有的每天计算一次,比如日活跃,有的是一周计算一次,比如周活跃
- 画像信息存储只是过程,最终的需求是要能够任意维度标签的快速查询,而在二维性数据库中,你无法对所有字段建立索引,人群筛选场景下查询效率将会极低
二、创建竖表-每个用户+每个标签=一条记录
- 这种方式应用于标签值不固定的场景,可以理解为宽表的空间换时间方案
| user_id |
标签类型 |
标签值 |
| 1 |
性别 |
男 |
| 1 |
年龄 |
15 |
| 2 |
性别 |
女 |
优点:
- 易于扩展,适用于标签不固定场景
- 存储无冗余,只存有值的标签项
- 计算友好,每一行记录都是一个单独的计算项
- 可以对标签类型+标签值建立联合索引,任意维度查询的场景性能会比较高
缺点:
- 数据量巨大,100万用户,每个用户100个标签,将会产生1亿条数据
- 查询不友好,比如我要统计性别=男,年龄=15的人,需要这样写:
select user_id from user_tags where (tag='sex' and tag_value='男') and (tag='age' and tag_value='15')
三、竖表+横表=》分开计算,定时聚合
- 通过竖表完成各统计项的计算,以及任意标签维度查询
- 定时将这些离散的数据汇聚到宽表中,用于用户画像基本信息的展示
- 结合,第一种和第二种,能够满足,用户画像自定义维度的查询,也能够满足用户标签信息的展示
- 除了数据量问题,没有其他问题
| user_id |
标签类型 |
标签值 |
| 1 |
性别 |
男 |
| 1 |
年龄 |
15 |
| 2 |
性别 |
女 |
定义汇聚为:
| user_id |
姓名 |
性别 |
| 1 |
老五 |
男 |
| 2 |
老四 |
女 |
四、ES 标签对象存储,rowKey为user_id,HBASE存储用户明细,通过user_id关联
- 早期的大数据画像存储方案
- es的每一条记录为一个文档,同时也为一个用户的画像信息,rowKey为user_id
- 人群筛选时,通过es查询出匹配的user_id集合,然后去Hbase中查询这批集合的明细,能够实现秒级的响应
五、倒排表,标签-》多个用户Id,bitmap方案
- ES搜索之所以快,功劳在于他的倒排索引上,所以又有了以下方案:
常见的描述是用户身上有哪些属性,而倒排索引是这个属性有哪些用户拥有
| 标签类型 |
标签值 |
user_ids |
| 性别 |
男 |
1,2 |
| 性别 |
发 |
3 |