数仓总结

 

15.1.1 数仓分几层?每层做什么的?

1)ODS层(原始数据层)

存储原始数据,直接加载原始日志、数据,数据保持原貌不做处理。

2)DWD层(明细层)

对ODS层数据进行清洗(去除空值、脏数据,超过极限范围的数据)

3)DWS层(服务数据层)

以DWD层为基础,进行轻度汇总。比如:用户当日、设备当日、商品当日。

4)ADS层(数据应用层)

15.1.2 在项目中是否自定义过UDF、UDTF函数,以及用他们处理了什么问题?

自定义过。

用UDF函数解析公共字段;用UDTF函数解析事件字段。

15.1.3 如何分析用户活跃?

在启动日志中统计不同设备id 出现次数。

15.1.4 如何分析用户新增?

用活跃用户表 left join 用户新增表,用户新增表中mid为空的即为用户新增。

15.1.5 如何分析用户1天留存?

留存用户=前一天新增 join 今天活跃

用户留存率=留存用户/前一天新增

15.1.6 如何分析沉默用户?

按照设备id对日活表分组,登录次数为1,且是在一周前登录。

15.1.7 如何分析本周回流用户?

本周活跃left join本周新增 left join上周活跃,且本周新增id和上周活跃id都为null

15.1.8 如何分析流失用户?

按照设备id对日活表分组,且七天内没有登录过。

15.1.9 如何分析最近连续3周活跃用户数?

按照设备id对周活进行分组,统计次数等于3次。

15.1.10 如何分析最近七天内连续三天活跃用户数?

1)查询出最近7天的活跃用户,并对用户活跃日期进行排名

2)计算用户活跃日期及排名之间的差值

3)对同用户及差值分组,统计差值个数

4)将差值相同个数大于等于3的数据取出,然后去重,即为连续3天及以上活跃的用户

15.1.11 整个文档中涉及的所有层级及表

15.2 Hive总结

15.2.1 Hive的架构

 

15.2.2 Hive和数据库比较

Hive 和数据库除了拥有类似的查询语言,再无类似之处。

1)数据存储位置

Hive 存储在 HDFS 。数据库将数据保存在块设备或者本地文件系统中。

2)数据更新

Hive中不建议对数据的改写。而数据库中的数据通常是需要经常进行修改的,

3)执行延迟

Hive 执行延迟较高。数据库的执行延迟较低。当然,这个是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,Hive的并行计算显然能体现出优势。

4)数据规模

Hive支持很大规模的数据计算;数据库可以支持的数据规模较小。

15.2.3 内部表和外部表

1)管理表:当我们删除一个管理表时,Hive也会删除这个表中数据。管理表不适合和其他工具共享数据。

2)外部表:删除该表并不会删除掉原始数据,删除的是表的元数据

15.2.4 窗口函数

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() 会根据顺序计算

15.2.5 在项目中是否自定义过UDF、UDTF函数,以及用他们处理了什么问题?

1)自定义过。

2)用UDF函数解析公共字段;用UDTF函数解析事件字段。

3)自定义UDF步骤:定义一个类继承UDF,重写evaluate方法

4)自定义UDTF步骤:定义一个类继承GenericUDTF,重写初始化方法、关闭方法和process方法。

15.2.6  4个By区别

1Sort By分区内有序;

2Order By全局排序,只有一个Reducer;

3Distrbute By类似MR中Partition,进行分区,结合sort by使用。

4 Cluster By当Distribute by和Sorts by字段相同时,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外还兼具Sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。

 

15.2.7 Hive优化

  • 1)MapJoin

如果不指定MapJoin或者不符合MapJoin的条件,那么Hive解析器会将Join操作转换成Common Join,即:在Reduce阶段完成join。容易发生数据倾斜。可以用MapJoin把小表全部加载到内存在map端进行join,避免reducer处理。

  • 2)行列过滤

列处理:在SELECT中,只拿需要的列,如果有,尽量使用分区过滤,少用SELECT *。

行处理:在分区剪裁中,当使用外关联时,如果将副表的过滤条件写在Where后面,那么就会先全表关联,之后再过滤。

  • 3)采用分桶技术
  • 4)采用分区技术
  • 5)合理设置Map

(1)通常情况下,作业会通过input的目录产生一个或者多个map任务。

主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小。

(2)是不是map数越多越好?

答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。

(3)是不是保证每个map处理接近128m的文件块,就高枕无忧了?

答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。

针对上面的问题2和3,我们需要采取两种方式来解决:即减少map数和增加map数;

  • 6)小文件进行合并

在Map执行前合并小文件,减少Map数:CombineHiveInputFormat具有对小文件进行合并的功能(系统默认的格式)。HiveInputFormat没有对小文件合并功能。

  • 7)合理设置Reduce

Reduce个数并不是越多越好

(1)过多的启动和初始化Reduce也会消耗时间和资源;

(2)另外,有多少个Reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,则也会出现小文件过多的问题;

在设置Reduce个数的时候也需要考虑这两个原则:处理大数据量利用合适的Reduce数;使单个Reduce任务处理数据量大小要合适;

  • 8)常用参数

// 输出合并小文件

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)数仓维度建模模型 
使用星型的建模方式

发布了77 篇原创文章 · 获赞 25 · 访问量 9199

猜你喜欢

转载自blog.csdn.net/TU_JCN/article/details/104922148