其实主要也可以看背诵稿,不过自己也整理一遍看看和背诵稿的区别
ETL : spark
行为域数据
1.日志前端埋点,生成日志数据
2.nginx负载均衡,日志服务器(采集程序)存储为日志文件
3.Flume采集日志文件tail dir source,写入hdfs hdfs sink
4.日志预处理
5.落hive数仓ODS层
业务域数据
1.业务系统增删改数据库,形成业务数据
2.Sqoop/DataX/ Kettle数据抽取
注: Kettle是一些传统企业比较熟悉的ETL(extract-transfer-load)工具
3.落hive数仓ODS层
4.增量合并处理
数据仓库&用户画像
hive
数据服务 OLAP平台
用户画像:数据量大 ,用HBASE
固定报表查询:将结果报表导入mysql或ck,写web接口
规范模型多维数据分析:KYLIN
自助多维分析:PRESTO
其他辅助系统
任务调度:阿兹卡班
元数据:atlas
层数越高存储时间越长
1)ODS层
数据内容:存放flume采集过来的原始日志
存储格式:以json格式文本文件存储
存储周期:3个月
2) DWD层
数据内容:对ODS层数据做ETL处理后的扁平化明细数据
存储格式:以orc / parquet文件格式存储
存储周期:6个月
3) DWS层
数据内容:根据主题分析需求,从DWD中轻度聚合后的数据
存储格式:以ORC/PARQUET文件格式存储
存储周期:1年
4) ADS层
数据内容:根据业务人员需求,从DWS计算出来的报表
存储格式:以ORC/PARQUET文件格式存储
存储周期:3年
ODS层:对应着外部数据源ETL到数仓体系之后的表!
DWD层:数仓明细层;一般是对ODS层的表按主题进行加工和划分;本层中表记录的还是明细数据;
DWS层:数仓服务层,宽表;
ADS层: 应用层,主要是一些结果报表!
hdfs数据导入hive,使用导入数据脚本。
ODS有“app埋点日志表”,在DWD就对应有“app埋点日志明细表”
注:在行为事件我们主要做了一些明细化加工和数据关联,形成一些宽表,比如,我们根据不同的事件类型,专门抽取了几张主题事件表(比如pv类事件明细表,广告类事件明细表,交互类事件明细表等),以便将数据进一步扁平化结构化,为后续impala,kylin等的对接提供便捷;
ODS有“订单主要信息表”(保存增量数据),在DWD也有“订单主要信息表”(保存全量快照和拉链表)
ETL:
清洗过滤
数据解析
session分割
gb sessionId
flatmap 按时间排序,遍历list,如果下一条时间-当前时间大于某个阈值,则更新sessionId,当for循环到下一个的时候就更新下一条的sessionId了。
数据规范化处理
数据集成(维度退化)
1,将日志中的GPS经纬度坐标解析成省、市、县(区)信息;(为了方便后续的地域维度分析)
2,将日志中的IP地址解析成省、市、县(区)信息;(为了方便后续的地域维度分析)
app端解析gps的经纬数据,web端解析ip
首先需要地理位置(省市区)的参考经纬度坐标点,调用库将经纬度坐标点编码成geohashcode。
广播知识库,先用gps查,如果没查到就用ip(目的是补充数据的省市区地理位置维度信息)。
web日志无法得到gps的经纬数据,但是有ip地址,ip地址也可以得到省市区。
ip地址格式:给一个ip字典和一个ip如何根据ip找到该ip在哪一段?
把ip转成整数,日志的ip也转成整数,把字典排序,二分查找。
生成全局用户标识(idmapping)
diviceid:一个设备登录多个账号
用户id:没登陆访问
设备产生了匿名的行为日志,该归属给谁?所以需要idmapping账号设备动态绑定(如果刚下载没登陆,就用设备id做标识)。
方案:维护一张表 设备,账号,score
1注:full join+nvl
2注:如果有device01,null
device01,uid01
的数据,肯定可以找到deviceid01和相应账号的绑定评分表,找到评分最高的uid把null填充就可以完成账号回补。
3注:如果没查到账号,也没查到device,就在redis里记录这个账号,对应自增id就是用户全局标识。如果查到了账号,就取到整数id,补充进事实表中,作为用户全局标识。如果查到了device,就把device更新成账号,不用新增全局标识。
新老访客标记
维度信息的构建
从业务表中抽取需要的维度表(商品信息表,用户注册信息表,商品品类表,品牌信息表……)
从用户画像表中抽取需要的维度(用户消费等级画像表,消费偏好画像表,活跃等级画像表)
从dwd数据中为本需求特别构建维度(如会话入口页面,会话跳出页面,是否是跳出会话,等)
利用程序自动生成(时间维表)
其他(比如,页面id、url对应的频道信息,可以根据规律人工构建;
devicetype对应的设备品牌厂家价位等信息,可以用爬虫)
大宽表开发:把各个渠道的维度都join进事实表。
连续活跃区间开发
中间表的设计:
方案1.拉链表
得到
– 2021-08-09 连续活跃区间记录中间表
1,2021-07-01,2021-07-01,2021-07-08
1,2021-07-01,2021-08-01,2021-08-02
2,2021-07-05,2021-07-05,2021-07-15
2,2021-07-05,2021-08-05,9999-12-31
3,2021-08-01,2021-08-01,2021-08-05
3,2021-08-01,2021-08-08,2021-08-08
4,2021-07-05,2021-07-05,2021-07-15
4,2021-07-05,2021-08-05,9999-12-31
逻辑:过滤出历史endDt=9999的,full join今天的,左边有右边没有就封闭,左边有右边有就不变,左边没有右边有就开新的。关键语法:nvl 再union
如果要加上维度分析的需求呢?
在全局的层面上的,为所有用户维护一张“维度信息表”
GUID, 省 ,市 ,区 ,设备型号 , 首访日期, 年龄, 性别, 会员等级
我所要的维度字段值全在一张表中,在统计分析时,中心表 只要关联 一级 维表,即可得到所有维度字段
方案2.bitmap
初始化
INSERT INTO TABLE dws.mall_app_ctn_bitmap PARTITION(dt='2021-09-26')
SELECT
guid,
sum(cast(pow(2,datediff('2021-09-26',dt)) as int)) as atv_bitmap
from dws.test_mall_app_dau
where datediff('2021-09-26',dt)<=30
group by guid
-- bitmap表初始化结果:
+-------+-------------+
| guid | atv_bitmap |
+-------+-------------+
| 1 | 33554759 |
| 2 | 33554525 |
| 4 | 16777563 |
+-------+-------------+
;
-- 更新逻辑sql:
-- (原来的值*2 + (今天活跃?1:0)) & 整数最大值
-- |1000000000000000000000000001011
-- 1|000000000000000000000000001011?
INSERT INTO TABLE dws.mall_app_ctn_bitmap PARTITION( dt='2021-09-27')
SELECT
nvl(bm.guid,dau.guid) as guid,
case
when bm.guid is not null and dau.guid is not null then (atv_bitmap * 2 + 1) & 2147483647
when bm.guid is not null and dau.guid is null then (atv_bitmap * 2) & 2147483647
else 1
end as atv_bitmap
FROM
(SELECT
guid,
atv_bitmap
FROM dws.mall_app_ctn_bitmap
WHERE dt='2021-09-26') bm
FULL JOIN
(SELECT
guid
FROM dws.test_mall_app_dau
WHERE dt='2021-09-27') dau
ON bm.guid = dau.guid
新用户留存分析
中间表制作方法:
挑出今天活跃的用户-首访日,gb今日-首访日的差,就可以得到今天的几日留存各有多少了。
select
’2021-06-06’ as calc_dt,
first_dt,
datediff(‘2021-06-06’,first_dt) sub,
count(if(rng_end=’9999-12-31’,1,null)) as ret_usr_cnt
From dws.usr_ctn_atv_rng
Where dt=’2021-06-06’
Group by datediff(‘2021-06-06’,first_dt)
漏斗模型开发
–步骤1:过滤出漏斗模型中关心的事件
–步骤2:留下满足条件的guid和eventid和ts即可
–步骤3:将每个用户的事件名称收集成一个数组,并按时间有序
–步骤4:利用正则匹配来计算每个人实现的最大步骤号
-- 完整sql: ------------------------------------
WITH tmp as (
SELECT guid
,concat_ws(',',sort_array(collect_list(concat_ws('_',ts || '',eventid)))) as events
FROM dwd.test_mall_app_evt_dtl
WHERE dt BETWEEN '2021-09-24' AND '2021-09-26'
AND (( eventid='e1' and properties['p1']='v1' )
OR
( eventid='e3' and properties['p2']='v5' )
OR
( eventid='e4')
OR
( eventid='e5' and properties['p8']='v8' ))
GROUP BY guid
)
/*
+-------+--------------------------------+
| guid | events |
+-------+--------------------------------+
| 1 | 1_e1,3_e3,5_e4,6_e5 |
| 2 | 1_e3,2_e4,3_e1,4_e5 |
| 3 | 1_e3,2_e4,3_e1,4_e5,5_e3,6_e4 |
+-------+--------------------------------+
*/
INSERT INTO TABLE dws.mall_app_fun PARTITION(dt='2021-09-26')
SELECT
guid,
'海家闪购' as funnel_name,
'2021-09-24' as window_start,
'2021-09-26' as window_end,
case
when regexp_extract(events,'.*?(e1).*?(e3).*?(e4).*?(e5).*?',4)='e5' then 4
when regexp_extract(events,'.*?(e1).*?(e3).*?(e4).*?',3)='e4' then 3
when regexp_extract(events,'.*?(e1).*?(e3).*?',2)='e3' then 2
when regexp_extract(events,'.*?(e1).*?',1)='e1' then 1
else 0
end as max_step
FROM tmp
归因分析 留个坑
在做一些运营活动,广告投放后,都需要去评估活动或者广告的效应;
我们的销量、拉新等业务目标,在广告投放或者运营活动组织后,有了明显的提升,但是这些提升是否是因为广告、运营活动导致的,需要有数据支撑!
这些数据分析,就属于 事件归因分析 的范畴!
而归因分析,又是一件非常复杂的运算:一个业务目标事件的达成,究竟是由哪些原因(待归因事件)引起的;待归因事件通常是事先会定好候选项!
比如,一个业务目标X,能够由A、C、F事件引起;
当一个用户完成了目标X,那么我们要分析他的X究竟是由ACF中哪一个事件所引起;
种类:
首次触点归因:待归因事件中,最早发生的事,被认为是导致业务结果的唯一因素
末次触点归因:待归因事件中,最近发生的事,被认为是导致业务结果的唯一因素
线性归因:待归因事件中,每一个事件都被认为对业务结果产生了影响,影响力平均分摊
位置归因:定义一个规则,比如最早、最晚事件占40%影响力,中间事件平摊影响力
时间衰减归因:越晚发生的待归因事件,对业务结果的影响力越大
用spark实现
先过滤出需要的用户行为序列,根据目标事件发生的次数进行分段(一个人可能做了多个目标事件)。
计算归因权重(调线性归因算法)。
行为路径分析
1.先获取一个事件名称对应事件id的字典表
2.将事件明细按照需求进行过滤
3.将过滤后的 事件表 关联 id字典表
4.按照guid收集他的事件id列表,并形成字符串
5.对字符串进行正则匹配
定期导入Hbase:spark转成Hfile(在hdfs)用hbase的bulkloader导进hbase中
固定维度组合:对应神策数据的鼠标点击维度组合的选择。解决方法:利用高阶聚合函数,一次性计算多维分析报表。
hive高阶函数withcube,指定组合顺序剪枝。但是不太好,有专门的用来做维度组合的Kylin。
行为域用户画像
用户活跃概况属性标签
用户交互事件属性标签
用户购物事件属性标签
用户运营位事件属性标签
流量报表开发
sqoop,可以在各种关系型数据库和hdfs中导入导出数据,底层原理是mr程序。
datax
导入策略:全量与增量。notepad
增量导入:当天相比昨天新增的或改变的导入。使用datax自定义sql功能筛选条件,根据业务表中的updatetime。
每日全量快照:增量导入+拉链表
为什么要拉链表:相比每日都存一次快照节省存储空间,而且也可以获得每日的状态。获得每日全量快照只需要在昨日的基础上与增量数据合并就行了。
拉链表逻辑:
对历史数据做修改,join上的9999就封闭(这一步行数不变)
union all今天的所有数据。取数就卡endtime。
和上面的区别,这个包含更新操作。join上表示更新,做封闭。上面join上表示继续连续登录,不变,还是9999。
订单表join各种维表gb分析。
画像分析:看字段需要哪些维表,然后一通join。
后端服务漏斗模型
前端表单提交,解析表单。前端要提交的json表单需要设计,后端编写一些类用于封装表单的数据
前端superset
可以连接presto,kylin
可以写sql
还可以选择图表类型
spark、hql、sqoop、kylin用脚本
脚本需要发送报警信息,短信或邮件。
Azkaban调度脚本
配置文件里面可以设置脚本的执行依赖(执行顺序),将脚本和配置文件打包。再web界面提交,可以传递参数,也可以配置失败重启策略。
配置文件示例# c.job
type=command
command=sh c.sh
dependencies=a,b
Atlas元数据管理
优势:和大数据组件深度整合。在hive中建表可以自动录入元数据
底层存储:图数据库
Atlas作用
数据分类管理
为元数据导入或定义业务导向的分类注释
定义,注释,以及自动捕获数据集和底层元素之间的关系
集中审计
捕获与所有应用,过程以及与数据交互的安全访问信息
捕获执行,步骤,活动等操作的信息;
搜索与血缘管理
可以根据classfication类别、关键字、数据资产类型等条件来快捷搜索相关元数据
AtlasWeb功能:分类,搜索,手动录入
Atlas自动获取元数据&追踪表的血缘关系:给Hive配Atlas钩子,在Hive中配一个参数。
在hive-env里面export Hive的额外jar包路径,hivs-site里面添加atlas hook,再配置altas的配置文件,拷贝到hive conf目录里面。
原理,在Hive执行语句的时候会调用钩子,摄取数据。已有的数据,可以对hive中已存在的表进行导入。
day9 02留个坑,hbase相关的知识
有的时候也需要直接导入导hbase,eg画像数据用于营销系统的。这时就用spark把数据变成hfile,再用bulkloader导入即可。
Kylin
关键词:预计算,多维分析,优化,cube
把中间表导入hbase用phoenix拼sql查询,少部分常看的可直接导报表。可以用Kylin,把Hive中的事实表和维度表和group sets给Kylin,Kylin可以完成group sets的base cube(全维度的gb)计算并且存在Hbase中,再查询的时候从base cube再进行计算效率很高。Kylin也提供jdbc接口,直接从Kylin取数就行了。
整个数据立方体称为1个cube,立方体中每个网格点称为1个cuboid,图中(A,B,C,D)和(A,D)都是cuboid;特别的,(A,B,C,D)称为Base cuboid。
cube的计算过程是逐层计算的,首先计算Base cuboid,然后计算维度数依次减少,逐层向下计算每层的cuboid。
cube的设计:留坑
维度剪枝:一种优化的方法。
划分聚合组
使用必选维度
使用层级维度
使用联合维度
Presto
纯内存计算引擎,不落盘,速度快,内存占用大
Presto是由Facebook开发的一个分布式SQL查询引擎, 它被设计为用来专门进行高速、实时的数据分析。它的产生是为了解决Hive的MapReduce模型太慢以及不能通过BI或Dashboards直接展现HDFS数据等问题。
Presto是一个纯粹的纯内存的计算引擎,它不存储数据,其通过Connector(类比mr中的inputformat组件)获取第三方Storage服务的数据。
在本项目中进行即席查询。
Presto数据管理模型
Presto使用Catalog、Schema和Table这3层结构来管理数据。
Catalog:就是数据源。Hive是数据源,Mysql也是数据源,Hive 和Mysql都是数据源类型,可以连接多个Hive和多个Mysql,每个连接都有一个名字。一个Catalog可以包含多个Schema,大家可以通过show catalogs 命令看到Presto连接的所有数据源。
Schema:相当于一个“库”,一个Schema包含多张数据表。
show schemas from 'catalog_xx’可列出catalog_xx下的所有schema。
Table:“数据表”,与一般意义上的数据库表相同。
show tables from 'catalog_xx.schema_yy’可查看catalog_xx.schema_yy下所有表。
在Presto中定位一张表的全名,结构为:数据源.数据库.数据表(catalog.schema.table)
例如 hive.db1.test,表示hive(catalog)下的 db1(schema)中test(表table)。
架构
Master-Slave架构
三个模块(角色):Coordinator、Discovery Service、Worker
Connector(数据源连接器)
Presto沿用了通用的Master-Slave架构,Coordinator即Presto的Master,Worker即其Slave,Discovery Service就是用来保存Worker结点信息的,通过HTTP协议通信,而Connector用于获取第三方存储的Metadata及原始数据等。
假如配置了Hive Connector,需要配置一个Hive MetaStore服务为Presto提供Hive元信息,Worker节点与HDFS交互读取数据。
Coordinator负责解析SQL语句,生成执行计划,分发执行任务给Worker节点执行;
Worker节点负责实际执行查询任务。
Worker节点启动后向Discovery Server服务注册,Coordinator从Discovery Server获得可以正常工作的Worker节点。
配置数据源的connector即可进行查询。
自我介绍的时候:
对整个大数据的生态都有一个比较完善的认识
首先是基于hive的离线数仓。采集,分层计算,维度建模,一些固定报表的产出。支持灵活的olap分析以及展示。
还包含了数据治理,任务调度等工作。
第二个是实时数仓与规则营销系统
这个有两个部分,一个是实时数仓。实时数仓就可以对外提供一个实时的看板,实时展现一些统计的指标。规则营销系统就可以根据用户的行为序列,判断是否匹配规则。他实现了规则的动态注入,完成了flink代码和规则逻辑的解耦,多个规则同时进行计算,根据时间的远近在不同的介质中查询。这个在用户的运营,比如说广告推送,还有实时的风控场景下都能用到。
还有一个是简易流计算系统
他是一个分布式的流计算框架,可以把节点部署在多台机器上。支持kafkaSource,自定义的算子,map,filter,aggregate算子,开窗运算,WaterMark语义并且可以处理一定的乱序数据。
介绍项目的时候
这个项目的数据源有两个,埋点数据和业务数据库mysql的数据,这里也对应了两个主题域,行为域对应了埋点数据,业务域对应了业务数据库的数据。埋点数据是先由nginx做一个负载均衡,均匀的发到日志采集服务器上,由日志采集服务器进行落盘。由flume使用taildirSource对文件进行监控和采集。落盘到hdfs,按照日期分区,这也就是ods层。然后由spark读取ods的数据进行etl,这里有一步很关键的是数据中有一些是匿名访问的,用户id为空,只有设备id,在etl的过程中使用一种方法把用户id补全。在dwd我们根据不同的事件类型,专门抽取了几张主题事件表。eg广告类事实表,用户流量事实表,互动类事实表。在dws就对dwd的数据关联一些维表形成宽表。ads对这些宽表进行简单的计算得到报表。数据服务这里是有用到了Kylin和Presto,Kylin是适合做固定维度组合的多维分析的预计算。Presto适合做即席查询。Kylin和Presto向下对接的是dws,向上对接的是SuperSet一个BI软件,SuperSet可以对接各种数据源用sql查询展示图表。业务域的话也是类似的处理,不过主要数据是用户订单。在ods到dwd的时候做了一个拉链表的处理。数据治理方面,写一些脚本sql监控hive表中数据的质量,用atlas对数据进行血缘追踪,元数据管理。用azakaban进行任务调度。介绍完了。
这是一个整体上的情况,这里面,您看看有哪些方面想详细了解?
nginx如何实现负载均衡
客户端的请求负载均衡的发到服务端
轮询,nginx把数据负载均衡的发送到日志采集服务器,日志采集服务器落盘。
数仓项目的数据采集模块怎么做的?
(正向代理,客户端到服务端,反向代理,服务端到客户端)
日志生成之后会发到公司后台的nginx服务器(web服务器,接收http请求)做反向代理(请求转发),nginx轮询发给日志采集服务器,日志采集服务器记到磁盘里。Flume读本地磁盘,如果不在一个局域网,还要部署中转点。中转点把数据写到hdfs。本架构模拟日志集群和hdfs集群不在一个局域网。一个网卡连日志集群局域网,另一个网卡连hdfs局域网。
上游Source读文件,下游Source监听网络端口,读网络消息。
上游Sink发送网络消息,下游Sink写hdfs。
上游taildirSource,avroSink
下游avroSource,hdfsSink
改进:下游高可用
下游汇聚节点弄一个备用的
上游agent2个sink,分别发往下游2个agent,加个sinkprocessor,failoverSinkProcessor,同时只有一个sink工作。
如果上游挂怎么办,写脚本监控进程。
flume组成,各个模块的功能
agent:一个flume节点,一个进程,包含三个组成
source:和数据源对接,获取数据
channel:内部缓存,解耦source和sink,削峰填谷,满足异步操作。
sink:往下一级agent或者最终存储系统
interceptors:在source将event放入channel之前,调用拦截器对event进行拦截和处理
channel selectors:source写入channel的策略
sink processor:写入sink的策略,默认(一对一),负载均衡,故障转移。
flume多久采一次
一直开着
上报延迟怎么办
数据被采集到hdfs的时候进入了不对的时间目录,添加拦截器,用拦截器抽取数据时间戳,放到event的header(对数据进行标识,来自哪个主机,时间)里面
上有配置:数据里要抽的字段是什么,在header里面叫什么。timestamp_fildername指定了时间的字段名。
为什么要使用这些source或者是sink
taildirSource,因为nginx落盘到文件里,hdfssink要写到hdfs里面。
file channel和memory channel有什么区别,分别在什么场景使用
File Channel是一个持久化的隧道(channel),他持久化所有的事件,并将其存储到磁盘中。因此,即使Java 虚拟机当掉,或者操作系统崩溃或重启,再或者事件没有在管道中成功地传递到下一个代理(agent),这一切都不会造成数据丢失。时效性要求较低,稳定性要求较高,不允许日志丢失。
Memory Channel是一个不稳定的隧道,其原因是由于它在内存中存储所有事件。如果java进程死掉,任何存储在内存的事件将会丢失。另外,内存的空间收到RAM大小的限制,而File Channel这方面是它的优势,只要磁盘空间足够,它就可以将所有事件数据存储到磁盘上。适合需要更高吞吐量的数据流。
flume内部原理
工作模式:
source中的数据统一封装成event,发给channel,发给sink。
拦截器:在传输过程中简单处理数据。工作在Source的后面,channel的后面,可以组成拦截器链。
channelSelector:一个agent一个source配多个channel,一个channel可接多个sink。选择发往channel的策略:轮询
sink消费能力弱,channel会不会丢失数据
不会,flume是由事务的,source到channel有事务,channel到sink有事务,保证
exactly only once,除非memorychannel,agent宕机或channel溢出
datax的内部结构是什么样的?
底层用是mr程序来读写。
把读和写的组件封装成插件,读插件->frameWork->写插件。
frameWork是整体的概念,channel是taskgroup的概念
DataX作业运行起来之后, Job监控并等待多个TaskGroup模块任务完成,等待所有TaskGroup任务完成后Job成功退出。否则,异常退出,进程退出值非0;
为什么不能用datax代替flume?
功能不一样,datax是用来进行离线数据同步的,flume是用来采集数据的。
数仓概念
数据仓库是一个面向主题的、集成的、相对稳定的、反映历史变化的数据集合,用于支持管理决策。
数仓有哪些主题域?哪些主题?那些报表?
行为域业务域:
主题:对应dwd的明细表,dwd广告类事件明细表,交互类事件明细表等,流量明细,用户渠道类事件明细表。
dws:就是对dwd的数据关联维度形成宽表,ads就是一些按照时间统计的报表。
行为域:
流量主题: 对客户端的流量进行整体的分析。得到多维分析的流量报表。
用户:对用户的行为进行分析,留存,漏斗分析,用户路径(筛选标签),用户行为归因分析。用户1-7日留存,漏斗分析报表,归因分析报表(对用户的某个行为如下单做归因,研究他之前的行为)。对用户做用户画像,打标签(这里主要是行为画像),得到用户行为画像表 。
**渠道:**对获取新用户的渠道进行分析,渠道来源展示表。
业务域:
**订单主题:**对用户的整体订单情况进行分析。
复购主题: 对用户的复购行为进行分析。
**用户主题:**对用户打消费画像,得到用户消费画像表。
数据建模的过程
数据建模往实际的讲就是中间表的设计,好的中间表可以更容易地支持上层的报表。
(1)选择业务过程
在业务系统中,挑选我们感兴趣的业务线,比如下单业务,支付业务,退款业务,物流业务,一条业务线对应一张事实表。
(2)声明粒度
数据粒度指数据仓库的数据中保存数据的细化程度或综合程度的级别。
声明粒度意味着精确定义事实表中的一行数据表示什么,应该尽可能选择最小粒度,以此来应各种各样的需求。
典型的粒度声明如下:
订单事实表中一行数据表示的是一个订单中的一个商品项。
支付事实表中一行数据表示的是一个支付记录。
(3)确定维度
维度的主要作用是描述业务是事实,主要表示的是“谁,何处,何时”等信息。
确定维度的原则是:后续需求中是否要分析相关维度的指标。例如,需要统计,什么时间下的订单多,哪个地区下的订单多,哪个用户下的订单多。需要确定的维度就包括:时间维度、地区维度、用户维度。
(4)确定事实
此处的“事实”一词,指的是业务中的度量值(次数、个数、件数、金额,可以进行累加),例如订单金额、下单次数等。
在DWD层,以业务过程为建模驱动,基于每个具体业务过程的特点,构建最细粒度的明细层事实表。事实表可做适当的宽表化处理。
事实表和维度表的关联比较灵活,但是为了应对更复杂的业务需求,可以将能关联上的表尽量关联上。
事实表类型
事务性事实表,稀疏表,只有发生了行为大进行记录,而且一旦插入就不能在更改,增量更新
事实表一般围绕着度量来建立,当度量产生的时候,事实记录就生成了
如果同时生成多个度量值的话,我们可以在一个事实表中建立多个事实
当我们的事实表中的事实比较多时,有可能多个事实不同时发生,如果同时生成的几率很小,我们称之为稀疏事实表
周期快照事实表
稠密表,每个周期内,不论周期内是否发生操作,都进行记录
周期快照事实表记录的确定的周期的数据,而累积快照事实表记录的不确定的周期的数据
累积快照事实表
代表的是完全覆盖一个事务或产品的生命周期的时间跨度,它它通常具有多个日期字段,
用来记录整个生命周期中的关键时间点。例如订单累计快照事实表会有付款日期,发货日期,收货日期等时间点。
数仓分层的介绍,每层的作用
ods:
为了考虑后续可能需要追溯数据问题,因此对于这一层就不建议做过多的数据清洗工作,原封不动地接入原始数据即可。
在项目里就是流量域就是flume采集磁盘文件到hdfs。业务域就是datax从mysql里面增量抽取。
dwd:
保持和ods一样的粒度,对ods的数据经过清洗,预处理进入dwd。在项目里流量域是对数据进行了ETL,简单清晰,补全地理位置信息,补全用户id。业务域就是做一个拉链表。
ODS有“app埋点日志表”,在DWD就对应有“app埋点日志明细表”
注:在行为事件我们主要做了一些明细化加工和数据关联,形成一些宽表,比如,我们根据不同的事件类型,专门抽取了几张主题事件表(比如pv类事件明细表,广告类事件明细表,交互类事件明细表等,流量明细事件表),以便将数据进一步扁平化结构化,为后续impala,kylin等的对接提供便捷;
ODS有“订单主要信息表”(保存增量数据),在DWD也有“订单主要信息表”(保存全量快照和拉链表) 做了一些表关联,比如订单数据,就把订单主要信息,订单商品详情信息,优惠券信息等进行关联,得到订单信息宽表等等;
dws:
该层是基于dws上的基础数据,整合汇总成分析某一个主题域的数据服务层,一般是宽表,用于提供后续的业务查询,OLAP分析,数据分发等。一般来说,该层的数据表会相对较少;一张表会涵盖比较多的业务内容,由于其字段较多,因此一般也会称该层的表为宽表。在项目里是对维度数据进行聚合,形成宽表。或者对事实表进行一些加工处理形成一些中间表
项目建设
这一层没有太固定的表模型预设
基本上都是根据后续的报表需求,做了一些轻度聚合计算。
比如,我们在统计交互事件的各种报表之前,我们会在dws层先按会话做一个会话聚合表,按用户一个用户聚合表,这样就可以得到每一个会话中各种交互事件的发生次数等结果,得到每一个用户上,各种交互事件的发生次数等结果,这些中间聚合,既可以为后面的报表统计服务,它本身可能也是可使用的数据产品,比如按用户聚合的交互事件统计,其本身就可以作为我们用户画像中的一个用户交互行为画像标签结果表;
在时间维度上,我们会做一些日粒度的,周粒度的,月粒度,季粒度的相关指标聚合计算;
在主题上,主要有流量分析,用户分析,交互事件分析,广告活动分析,转化分析,订单分析,GMV分析、购物车分析等
ads:
该层主要是提供给数据产品和数据分析使用的数据,一般会存放在ES、Redis、PostgreSql等系统中供线上系统使用;也可能存放在hive或者Druid中,供数据分析和数据挖掘使用,比如常用的数据报表就是存在这里的。在项目里是在hbase存储结果的报表,或者在Kylin和Presto中给外部提供查询服务的数据。
分层的作用,为什么分层
1、清晰数据结构:每一个数据分层都有它的作用域和职责,在使用表的时候能更方便的定位和理解
2、减少重复开发:规范数据分层,开发一些通用的中间层数据,能够减少极大地重复计算
3、便于维护
4、统一数据口径:通过数据分层,提供统一的数据出口,统一对外输出的数据口径
5、复杂问题简单化:将一个复杂的任务分解成多个步骤来完成,每一层解决特定的问题
了解维度建模吗,大概是什么样的(维度建模的介绍)
维度建模表示每个业务过程包含的事实表,事实表里面存储事件的数值化度量,围绕事实表的是多个维度表,维度表包含事件发生的实际存在的文本环境。
数仓是用的范式建模还是维度建模,为什么(维度建模和范式建模的对比,好处)
它与实体-关系建模有很大的区别,实体-关系建模是面向应用,遵循第三范式,以消除数据冗余为目标的设计技术,表的数量多,查询要关联很多表,麻烦且性能低下。维度建模是面向分析,为了提高查询性能可以增加数据冗余,反规范化的设计技术。维度建模的预处理开销大,数据冗余多,正好可以用大数据的分布式存储和分布式计算解决。
星型模型,星座模型,雪花模型介绍
当所有的维度表都是和事实表直接相连的时候
有的维度表没有直接和事实表相连,而是通过其他维度表
1)星型模型因为数据的冗余所以很多统计查询不需要做外部的连接,因此一般情况下效率比雪花模型要高。
2)星型模型不用考虑很多正规化的因素,设计和实现都比较简单。
3)雪花模型由于去除了冗余,有些统计就需要通过表的连接才能产生,所以效率不一定有星型模型高。
4)正规化也是一种比较复杂的过程,相应的数据库结构设计、数据的ETL、以及后期的维护都要复杂一些。因此在冗余可以接受的前提下,实际运用中星型模型使用更多,也更有效率。
数仓和数据集市有啥区别
(1)数据仓库:基于整个企业的数据模型建立,面向企业范围内的主题;数据集市面向部门。
(2)数仓存储整个企业内非常详细的数据;数据集市数据详细程度低一些,包含概要和综合数据多一些。
(3)数据集市的数据组织一般采用星形模型。大型数仓的数据组织,星形或雪花形都可以。
(4)数据集市较少保留历史数据。
用户宽表和其他宽表有没有考虑过数据口径一致性问题
数据口径是什么:计算数据的标准。
数据口径举例
统一数据口径的方法:建立中间表,数据口径映射表
ETL步骤
抽取(extract)到ods、转换(transform)、加载(load)到dwd
数据治理是什么?
通过采集、传输、储存等一系列标准化流程将原本零散的数据变成格式规范、结构统一的数据,同时对其进行严格规范的综合数据监控,保证数据质量;然后对这些标准化的数据进行进一步的加工分析,形成具有指导意义的业务监控报表、业务监控模型等,来帮助企业进行辅助决策。
在项目里就是元数据管理还有数据质量管理。
什么阶段进行数据清洗?
ETL阶段,准确的说是T也就是转换阶段。
数据量很大的时候每层都进行数据清洗吗?如何解决
不需要吧,其实没太懂这个问题是什么意思。
ETL过程中,数据出现问题了如何预警?
要看是什么问题,如果是数据质量问题可以写hive程序去统计数据的质量(比如字段空的率),写脚本监控这个程序,然后除了问题就发邮件报警。
元数据如何管理
使用atlas
Atlas元数据管理
优势:和大数据组件深度整合。在hive中建表可以自动录入元数据
底层存储:图数据库
Atlas作用
数据分类管理
为元数据导入或定义业务导向的分类注释
定义,注释,以及自动捕获数据集和底层元素之间的关系
集中审计
捕获与所有应用,过程以及与数据交互的安全访问信息
捕获执行,步骤,活动等操作的信息;
搜索与血缘管理
可以根据classfication类别、关键字、数据资产类型等条件来快捷搜索相关元数据
AtlasWeb功能:分类,搜索,手动录入
Atlas自动获取元数据&追踪表的血缘关系:给Hive配Atlas钩子,在Hive中配一个参数。
在hive-env里面export Hive的额外jar包路径,hivs-site里面添加atlas hook,再配置altas的配置文件,拷贝到hive conf目录里面。
原理,在Hive执行语句的时候会调用钩子,摄取数据。已有的数据,可以对hive中已存在的表进行导入。
如何保障数据质量
写一些统计数据质量的sql脚本,定时执行,发送邮件通知或者报警。
数据延迟怎么办
数据延迟的原因,网络传输,数据积压。在flume设置拦截器,把数据的header的timestamp设置为eventTime,这样可以使数据进入正确的目录。晚一定时间计算,比如说0.30计算前一天数据。
数据服务是什么?
数仓对外提供的查询和分析服务。
数据服务怎么做的:
固定报表的查询:存在hbase,对外提供查询接口。
规范多维聚合在线查询分析:Kylin,对接dwd层多维分析预计算。提前把可能的各种“维度组合”进行指标聚合计算,则在分析师进行维度分析时,只需要直接取预计算好的结果即可,可大大改善分析师多维分析时的查询时效性。使用jdbc接口进行查询。
优化:源端优化(改善表的质量,分区等),维度剪枝(去掉不需要的维度组合)。
灵活即席查询查询服务:Presto。后端springboot整合jdbc,前端superset做报表。
spark、hql、sqoop、kylin用脚本
脚本需要发送报警信息,短信或邮件。
Azkaban调度脚本
配置文件里面可以设置脚本的执行依赖(执行顺序),将脚本和配置文件打包。再web界面提交,可以传递参数,也可以配置失败重启策略。
配置文件示例# c.job
type=command
command=sh c.sh
dependencies=a,b
idmapping: 背景:日志数据里面有设备id和用户id,有的时候因为用户id是空的,需要知道是哪个用户登陆的,给用户id做一个补全?如果只用设备id,有可能一个设备有多个用户登录。怎么做呢?维护一张用户id和设备id的绑定表。id,did,score。每天根据当天的登陆情况先计算当天的表。然后join历史的表,这里用到nvl函数。如果是join上了就相加,join不上就扣除一定的值,是新用户就增加这一行。查redis如果没查到账号,也没查到device,就在redis里记录这个账号,对应自增id就是用户全局标识。用redis的自增id作为用户唯一标识,如果查到了账号,就取到整数id,补充进事实表中,作为用户全局标识。如果查到了device,就把device更新成账号,不用新增全局标识。新老访客标记。在程序的一开始取出最大的自增id,然后判断用户的id,如果大于一开始最大的id就是新访客。
连续活跃区间记录表: 目的:记录一个用户的连续活跃区间情况,以满足各
种指标的活跃度分析。
最近一个月内,有过连续活跃10天的用户
最近一个月内,每个用户的平均活跃天数
最近一个月内,连续活跃[1-10)天的人数,[10-20)天的人数,[20+ 天的人数
任意指定的一段日期范围内,连续活跃5+天的人(比如,12-01,12-02,12-03连续3天活跃的人)
最近30天内,沉默天数超过3的有多少人,超过5天有多少人
两种方案:
1.拉链表思想
1,2021-07-01,2021-07-01,2021-07-08
1,2021-07-01,2021-08-01,2021-08-02
2,2021-07-05,2021-07-05,2021-07-15
2,2021-07-05,2021-08-05,9999-12-31
3,2021-08-01,2021-08-01,2021-08-05
3,2021-08-01,2021-08-08,2021-08-08
4,2021-07-05,2021-07-05,2021-07-15
4,2021-07-05,2021-08-05,9999-12-31
逻辑:过滤出历史endDt=9999的,full join今天的,左边有右边没有就封闭,左边有右边有就不变,左边没有右边有就开新的。关键语法:nvl 再union
如果要加上维度分析的需求呢?
在全局的层面上的,为所有用户维护一张“维度信息表”
GUID, 省 ,市 ,区 ,设备型号 , 首访日期, 年龄, 性别, 会员等级
我所要的维度字段值全在一张表中,在统计分析时,中心表 只要关联 一级 维表,即可得到所有维度字段
讲,先介绍这个表,他不是单纯的计算连续登录,而是做一张中间表,可以很方便的计算各种连续登录的指标。比如最近三十天登陆几天,最长连续登陆几天。借用拉链表的一个思想。维护这样的一张表,用户,startdate,enddate,一条数据代表用户的一次活跃区间。每个用户会有多条数据,因为一个用户会有多个活跃区间。如果当天活跃了,enddate就是9999,没活跃就区间封闭,enddate变成当天。封闭了的数据就不会改变了。更新操作是先把没封闭的数据过滤出来,然后full join当天的数据,nvl如果以前的有今天的没有,就封闭区间,以前的有今天的也有就不变,以前的没有今天的有就新增,startdate=今天,enddate=9999,然后再将join的结果union all之前的数据过滤掉enddate=9999就完成了今天的更新。
方案2.bitmap
初始化
INSERT INTO TABLE dws.mall_app_ctn_bitmap PARTITION(dt='2021-09-26')
SELECT
guid,
sum(cast(pow(2,datediff('2021-09-26',dt)) as int)) as atv_bitmap
from dws.test_mall_app_dau
where datediff('2021-09-26',dt)<=30
group by guid
-- bitmap表初始化结果:
+-------+-------------+
| guid | atv_bitmap |
+-------+-------------+
| 1 | 33554759 |
| 2 | 33554525 |
| 4 | 16777563 |
+-------+-------------+
;
-- 更新逻辑sql:
-- (原来的值*2 + (今天活跃?1:0)) & 整数最大值
-- |1000000000000000000000000001011
-- 1|000000000000000000000000001011?
INSERT INTO TABLE dws.mall_app_ctn_bitmap PARTITION( dt='2021-09-27')
SELECT
nvl(bm.guid,dau.guid) as guid,
case
when bm.guid is not null and dau.guid is not null then (atv_bitmap * 2 + 1) & 2147483647
when bm.guid is not null and dau.guid is null then (atv_bitmap * 2) & 2147483647
else 1
end as atv_bitmap
FROM
(SELECT
guid,
atv_bitmap
FROM dws.mall_app_ctn_bitmap
WHERE dt='2021-09-26') bm
FULL JOIN
(SELECT
guid
FROM dws.test_mall_app_dau
WHERE dt='2021-09-27') dau
ON bm.guid = dau.guid
漏斗分析
计算用户的转化率,某项活动的完成率
–步骤1:过滤出漏斗模型中关心的事件()
–步骤2:留下满足条件的guid和eventid和ts即可
–步骤3:将每个用户的事件名称收集成一个数组,并按时间有序
–步骤4:利用正则匹配来计算每个人实现的最大步骤号
归因分析
在做一些运营活动,广告投放后,都需要去评估活动或者广告的效应;
我们的销量、拉新等业务目标,在广告投放或者运营活动组织后,有了明显的提升,但是这些提升是否是因为广告、运营活动导致的,需要有数据支撑!
这些数据分析,就属于 事件归因分析 的范畴!
而归因分析,又是一件非常复杂的运算:一个业务目标事件的达成,究竟是由哪些原因(待归因事件)引起的;待归因事件通常是事先会定好候选项!
比如,一个业务目标X,能够由A、C、F事件引起;
当一个用户完成了目标X,那么我们要分析他的X究竟是由ACF中哪一个事件所引起;
种类:
首次触点归因:待归因事件中,最早发生的事,被认为是导致业务结果的唯一因素
末次触点归因:待归因事件中,最近发生的事,被认为是导致业务结果的唯一因素
线性归因:待归因事件中,每一个事件都被认为对业务结果产生了影响,影响力平均分摊
位置归因:定义一个规则,比如最早、最晚事件占40%影响力,中间事件平摊影响力
时间衰减归因:越晚发生的待归因事件,对业务结果的影响力越大
用spark实现
先过滤出需要的用户行为序列,根据目标事件发生的次数进行分段(一个人可能做了多个目标事件)。
计算归因权重(调线性归因算法)。
数仓数据量有多大
几十张表
项目问题排查应该怎么做?
看日志,根据日志里面更具体的报错信息进行查询。
最近项目中遇到了什么样的难点吗?
关于业务的一些相关设计比较难,比如说idmapping,中间表的数据。建模的设计。
了解实时和离线数仓吗,有啥区别
一、技术栈上,离线一般hive spark hdfs等,实时flink kafka hbase
二、分层上,离线分层更多,实时相对减少。建模都采用维度建模方法论,业务上离线的分析较为复杂。
三、实效性上,实时更加实时,延时控制在秒级别,离线则是T+1级别。
四、技术实现和运维上,实时相对比较困难,其储存使用kafka ,不可查询,排查问题比较困难。
五、业务需求上,离线多于实时。