1)ODS层(原始数据层)
存储原始数据,直接加载原始日志、数据,数据保持原貌不做处理。
2)DWD层(明细层)
对ODS层数据进行清洗(去除空值、脏数据,超过极限范围的数据)
3)DWS层(服务数据层)
以DWD层为基础,进行轻度汇总。比如:用户当日、设备当日、商品当日。
4)ADS层(数据应用层)
自定义过。
用UDF函数解析公共字段;用UDTF函数解析事件字段。
在启动日志中统计不同设备id 出现次数。
用活跃用户表 left join 用户新增表,用户新增表中mid为空的即为用户新增。
留存用户=前一天新增 join 今天活跃
用户留存率=留存用户/前一天新增
按照设备id对日活表分组,登录次数为1,且是在一周前登录。
本周活跃left join本周新增 left join上周活跃,且本周新增id和上周活跃id都为null
按照设备id对日活表分组,且七天内没有登录过。
按照设备id对周活进行分组,统计次数等于3次。
1)查询出最近7天的活跃用户,并对用户活跃日期进行排名
2)计算用户活跃日期及排名之间的差值
3)对同用户及差值分组,统计差值个数
4)将差值相同个数大于等于3的数据取出,然后去重,即为连续3天及以上活跃的用户
Hive 和数据库除了拥有类似的查询语言,再无类似之处。
1)数据存储位置
Hive 存储在 HDFS 。数据库将数据保存在块设备或者本地文件系统中。
2)数据更新
Hive中不建议对数据的改写。而数据库中的数据通常是需要经常进行修改的,
3)执行延迟
Hive 执行延迟较高。数据库的执行延迟较低。当然,这个是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。
4)数据规模
Hive支持很大规模的数据计算;数据库可以支持的数据规模较小。
1)管理表:当我们删除一个管理表时,Hive也会删除这个表中数据。管理表不适合和其他工具共享数据。
2)外部表:删除该表并不会删除掉原始数据,删除的是表的元数据
1)窗口函数:
(1) OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变而变化。常用partition by 分区order by排序。
(2)CURRENT ROW:当前行
(3)n PRECEDING:往前n行数据
(4) n FOLLOWING:往后n行数据
(5)UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点
(6) LAG(col,n):往前第n行数据
(7)LEAD(col,n):往后第n行数据
(8) NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。
2)排序函数:
(1)RANK() 排序相同时会重复,总数不会变
(2)DENSE_RANK() 排序相同时会重复,总数会减少
(3)ROW_NUMBER() 会根据顺序计算
1)自定义过。
2)用UDF函数解析公共字段;用UDTF函数解析事件字段。
3)自定义UDF步骤:定义一个类继承UDF,重写evaluate方法
4)自定义UDTF步骤:定义一个类继承GenericUDTF,重写初始化方法、关闭方法和process方法。
1)Sort By:分区内有序;
2)Order By:全局排序,只有一个Reducer;
3)Distrbute By:类似MR中Partition,进行分区,结合sort by使用。
4) Cluster By:当Distribute by和Sorts by字段相同时,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外还兼具Sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。
如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。
列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。
行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。
(1)通常情况下,作业会通过input的目录产生一个或者多个map任务。
主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小。
(2)是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。
(3)是不是保证每个map处理接近128m的文件块,就高枕无忧了?
答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。
针对上面的问题2和3,我们需要采取两种方式来解决:即减少map数和增加map数;
在Map执行前合并小文件,减少Map数:CombineHiveInputFormat具有对小文件进行合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能。
Reduce个数并不是越多越好
(1)过多的启动和初始化Reduce也会消耗时间和资源;
(2)另外,有多少个Reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;
在设置Reduce个数的时候也需要考虑这两个原则:处理大数据量利用合适的Reduce数;使单个Reduce任务处理数据量大小要合适;
// 输出合并小文件
SET hive.merge.mapfiles = true; -- 默认true,在map-only任务结束时合并小文件
SET hive.merge.mapredfiles = true; -- 默认false,在map-reduce任务结束时合并小文件
SET hive.merge.size.per.task = 268435456; -- 默认256M
SET hive.merge.smallfiles.avgsize = 16777216; -- 当输出文件的平均大小小于该值时,启动一个独立的map-reduce任务进行文件merge
32GB内存 +1TB固态硬盘 + 1TB机械硬盘
项目数据流程:用户行为数据(js埋点日志数据) 业务数据(数据库的数据)
用户行为数据,通过js埋点进行采集数据,使用flume去采集日志服务器的日志数据
用户行为日志分为两大类:
1、用户行为日志:基础数据,用户操作数据
2、app启动日志,每启动一次app,都会打印一条启动日志
用户操作数据的一条数据包含两部分:
1、基本公共字段:cm对应的都是安卓手机公共字段
2、用户的行为事件字段:商品列表页,商品点击,商品详情,广告,消息通知
活跃,评论,收藏,点赞,错误日志
启动日志和用户行为日志,混在一个文件里面了
模拟一个java程序去生成日志数据==》使用flume进行采集 node01和node02都去采集 ==》 汇总到node03 ==》通过node03的flume将数据保存到hdfs上面去了
flume
在flume采集的时候将启动日志,以及用户行为日志 分开,校验日志的格式是否是一个标准的json格式,如果不是标准的json,直接丢掉
自定义flume的拦截器,来实现数据的区分,以及粗略的ETL的过滤,过滤脏数据,将不同类型的数据进行分开
java编写flume的拦截器代码,maven打包上传到服务器,配置node01与node02的flume-client.conf时,source里添加拦截器的类型为刚刚打包的拦截器类型。
node01以及node02收集日志
source:tailDirsource 支持事务处理
channel: memoryChannel,fileChannel(实际工作当中使用比较多)
sink:avro sink
node03,汇总node01与node02数据,上传到hdfs,使用lzo的压缩方式了
source:avro source
channel: memorychannel fileChannel
sink: hdfsSink
数据仓库的分层:
ods原始数据层:完整的保存hdfs的数据,启动日志表 、事件日志表
dw数据仓库层:通过解析ods层的数据,将启动日志解析成为一张表
将用户的事件日志,解析成为11张表
dws层:主要就是针对12张表进行各种维度的统计分析
app数据展示层:数据报表的展示
分层好处:复杂的事情给他简单化,每一层相互进行隔绝
离线的数仓做的是T+1的任务,在实际工作当中,每天都会分析前一天的数据,表示数据的分析结果需要延迟一天
udf讲过,udtf没有讲过
开启hive本地模式以加快hive查询速度,yarn分配资源是很慢的
set hive.exec.mode.local.auto=true;
从ods层解析过来的==》就两张表 启动日志表 用户行为表
dwd层:从ods层解析过来的启动日志表
用户行为表:从ods层的用户行为表来进行解析 ==》 1张ods层用户行为表,解析成为了11张表
get_json_object
自定义UDF 以及UDTF用于来解析ods层的用户行为表
通过dwd层的表来实现各种维度的统计:
用户活跃的维度:统计当日、当周、当月活动的每个设备明细
统计每日活跃设备明细:启动日志表:每个设备启动一次都会有一个启动日志表
dwd层到dws层==》使用脚本进行控制
dws层==》一些指标的汇总到ads层==》使用脚本进行控制
sql是一个必备的技能,拿来就用
业务逻辑:如何分层,有哪些表,每个表里面有哪些字段,面试必备
hive的技能知识:轻车熟路,拿来就用的
回顾整个数仓过程:做了用户行为数据仓
使用flume采集数据 =》flume汇总 ==》将数据保存到hdfs上面去了 ==》 创建hive表映射ods层
==》 自定义hive的函数udf,udtf,解析启动日志以及事件的日志 ==》到了dwd层 ==》dws层 1变11张表
==》ads层 统计各种指标结果
使用shell脚本来实现程序的自动化的运行
将埋点的日志数据都处理完了
表的分类:
实体表:类似于我们创建的javaBean映射数据库当中的表 User表 , 商品表,商家表,销售员表
维度表:码表 其实就是一些固定的值的码表 字典表 省市区县
订单表面 ==》很多订单状态 {创建一张订单状态表}
事务性的事实表:表里面的数据,一旦产生就不会变了
做支付的同学:交易流水号一旦产生就没法再更改了
交易流水,操作日志,出库入库记录
周期性的事实表:随着业务发展,不断产生的数据
请假、贷款申请,随着批
请求流程:主管进行审批 ==》部门审批 ==》老总进行审批
贷款申请:==》第一层审批 ==》第二层审批 ==》 第三层审批
对照分类:将你们的系统当中使用的表进行分类
表的同步策略:从mysql里面用什么方式将数据同步到hdfs里面来
全表同步:
增量同步:
增量 + 修改数据的同步
数据同步策略:
全量表: 全表所有的数据都同步一次
增量表:只同步新增的数据
新增及变化表:新增的数据以及修改的数据都进行同步
拉链表:就是用于解决hive当中单个字段更新的问题 可以细致的观察到每条数据每一个时间段的发展变化情况
业务数据仓库如何实现:
sqoop导入数据到hdfs ==》 ods层创建表映射hdfs的数据 ==》 dwd层进行数据的汇总(商品和分类表进行了汇总)
==》dws层 主要就是针对数据进行聚合操作 ==》ads层做数据报表
数据可视化:可以通过sqoop将hive当中ads层的数据,导出到mysql做报表展示
项目总结:
10.2 数仓理论 背下来
1)表的分类:实体表、维度表、事务型事实表、周期型事实表
2)表的同步策略:
实体表(全量)
维度表(全量)
事务型事实表(增量)
周期型事实表(新增和变化、拉链表)
4)数仓维度建模模型 使用星型的建模方式