项目部署

虚拟机环境配置下载

整体设计

日志划分

业务日志批量更新,用户行为日志实时更新

虚拟机

虚拟机登录 root root
sudo systemctl start/status mysqld
mysql -uroot -p '000000'
gmailbin/sqoop list-databases --connect jdbc:mysql://warehouse:3306/ --username root --password 000000hadoop通过yarn控制datanode的资源配置,通过zookeeper控制namenode的高可用(数据同步,主从选举),zk和yarn无关
kafka通过zk记录注册的broker信息,选举leader,消费组reblance/opt/module/hadoop-3.1.3
启动hadoop
sbin/start-dfs.sh
启动yarn
sbin/start-yarn.sh
启动zk
zookeeper-3.5.7/bin/zkServer.sh start        /status看状态群启/停hadoop/yarn
/home/atguigu/bin
sh hdp.sh start/stop
启停zookeeper
sh zk.sh/stop
启停kafka
sh kf.sh start/stop
启停flume采集,channel存kafka上
f1.sh
启停flume消费上个flume的kafka channel,通过file channel
f2.sh
(flume默认按照机器时间来判定数据落盘位置,会造成数据0点飘逸
所以flume需要代码自定义拦截器设置按照日志产生的时间戳来判定数据落盘位置,
通过读取数据body解析日志内提前设定好的时间戳字段,然后赋值给flume header时间戳)cluster.sh 包含上面所有熟悉业务表含义,表结构
结合业务过程分析数据变化

维度表/事实表整体设计

维度设计过程

选择业务过程:确认有哪些事实表
声明粒度:每张事实表的每行数据是什么,粒度尽可能小
确认维度:确认如相关事实表的用户,地区等维度。事实表确认维度外键
确认事实:确认事实表度量值字段事实表三个分类
事务型事实表:适合不发生变化的事实表,通常增量同步
周期性快照事实表:适合不保留所有数据,只保留固定时间间隔数据。通常全量同步
累计型快照事实表:用于跟踪业务事实的变化

维度表设计

新增和变化表和增量表都可以用拉链表来记录(9999-99-99和正常日期分区,新旧full join实现)

事实表设计

有时候如评价字段理论上是维度内容,不属于维度外键和度量值
但评价维度字段很少,为了提高性能可以维度退化,将评价字段直接写入评价事实表

维度和事实关联

1 设计业务过程的时候,需要考虑订单/订单详情的类似情况。比如订单详情数据量更大,后续做分析很多时候并不需要详情的信息,所以添加一个订单事实表可以提高分析效率

2 DWT对DWS层对汇聚的时候,很多情况DWS和DWD是完全相同的计算,仅仅是如时间长短的汇聚区别,为了避免重复计算。可以一次计算保存在一个宽表,来记录不同时间粒度的汇聚。后续直接读取宽表即可

DWD业务日志维度表具体设计(批量sqoop装载获取)

一 sqoop 装载数据
二 全量同步表入hive

如业务维度表,全量表分区规划

三 新增和变化同步表入hive

新增和变化的用户表可以用拉链表记录,并动态分区写入

如用户维度表

1 动态分区和静态分区区别

表象:静态分区与动态分区的主要区别在于静态分区是手动指定,而动态分区是通过数据来进行判断。详细来说,静态分区的列实在编译时期,通过用户传递来决定的;动态分区只有在SQL执行时才能决定
深层次:动态分区与静态分区还有一个细微的差别是,静态分区一 定会创建分区,不管SELECT语句的结果有没有数据。而动态分区,只有在SELECT结果的记录数>0的时候,才会创建分区。因此在不同的业务场景下,可能会选择不同的方案。

另外使用动态分区时需要注意的比较重要的一点是,动态分区会为每一个分区分配reduce数。比如说你在脚本上面写了:set mapred.reduce.tasks=100;

并且有两个分区:pt, if_online。如果结果集中pt=20121023,if_online=0/1,那么它就会为pt=20121023/if_online=0,pt=20121023/if_online=1各分配100个reduce。也就是说,namenode会同时处理200个文件的写操作。这在分区值很多的情况下,会成为一个灾难,容易直接把namenode给搞挂掉,是非常危险的。因此使用动态分区时,一定要清楚地知道产生的动态分区值,并且合理地设置reduce数量

2 Why 拉链表

3 用户拉链表分区规划走向

4 SQL实现思路

with
tmp as
(selectold.id old_id,old.login_name old_login_name,old.nick_name old_nick_name,old.name old_name,old.phone_num old_phone_num,old.email old_email,old.user_level old_user_level,old.birthday old_birthday,old.gender old_gender,old.create_time old_create_time,old.operate_time old_operate_time,old.start_date old_start_date,old.end_date old_end_date,new.id new_id,new.login_name new_login_name,new.nick_name new_nick_name,new.name new_name,new.phone_num new_phone_num,new.email new_email,new.user_level new_user_level,new.birthday new_birthday,new.gender new_gender,new.create_time new_create_time,new.operate_time new_operate_time,new.start_date new_start_date,new.end_date new_end_date
from
(selectid,login_name,nick_name,name,phone_num,email,user_level,birthday,gender,create_time,operate_time,start_date,end_datefrom dim_user_infowhere dt='9999-99-99'
) old
full outer join
(selectid,login_name,nick_name,md5(name) name,md5(phone_num) phone_num,md5(email) email,user_level,birthday,gender,create_time,operate_time,'2020-06-15' start_date,'9999-99-99' end_datefrom ods_user_infowhere dt='2020-06-15'
) new
on old.id=new.id
)
insert overwrite table dim_user_info partition(dt)
selectnvl(new_id,old_id),nvl(new_login_name,old_login_name),nvl(new_nick_name,old_nick_name),nvl(new_name,old_name),nvl(new_phone_num,old_phone_num),nvl(new_email,old_email),nvl(new_user_level,old_user_level),nvl(new_birthday,old_birthday),nvl(new_gender,old_gender),nvl(new_create_time,old_create_time),nvl(new_operate_time,old_operate_time),nvl(new_start_date,old_start_date),nvl(new_end_date,old_end_date),nvl(new_end_date,old_end_date) dt
from tmp
union all
selectold_id,old_login_name,old_nick_name,old_name,old_phone_num,old_email,old_user_level,old_birthday,old_gender,old_create_time,old_operate_time,old_start_date,cast(date_add('2020-06-15',-1) as string),cast(date_add('2020-06-15',-1) as string) dt
from tmp
where new_id is not null and old_id is not null;

注:事实表实现方式和维度表一样

DWD用户行为日志(实时flume+kafka获取)

页面埋点日志和启动日志
get_json_object函数解析json日志数据,写入hive mysql表中(启动日志,页面日志,动作日志,曝光日志,错误日志表)



分区走向

动作日志表Hive UDTF设计

java代码自定义UDTF实现一列转一列多行
jar包导入hdfs user/hive/jars路径,创建永久函数和jar包class关联,hive内调用函数即可

public class ExplodeJSONArray extends GenericUDTF {@Overridepublic StructObjectInspector initialize(ObjectInspector[] argOIs) throws UDFArgumentException {// 1 参数合法性检查if (argOIs.length != 1) {throw new UDFArgumentException("explode_json_array 只需要一个参数");}// 2 第一个参数必须为string//判断参数是否为基础数据类型if (argOIs[0].getCategory() != ObjectInspector.Category.PRIMITIVE) {throw new UDFArgumentException("explode_json_array 只接受基础类型参数");}//将参数对象检查器强转为基础类型对象检查器PrimitiveObjectInspector argumentOI = (PrimitiveObjectInspector) argOIs[0];//判断参数是否为String类型if (argumentOI.getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.STRING) {throw new UDFArgumentException("explode_json_array 只接受string类型的参数");}// 3 定义返回值名称和类型List<String> fieldNames = new ArrayList<String>();//装列名List<ObjectInspector> fieldOIs = new ArrayList<ObjectInspector>();//装列对应的类型fieldNames.add("items");fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);}public void process(Object[] objects) throws HiveException {// 1 获取传入的数据,第一列的数据String jsonArray = objects[0].toString();// 2 将string转换为json数组JSONArray actions = new JSONArray(jsonArray);// 3 循环一次,取出数组中的一个json,并写出for (int i = 0; i < actions.length(); i++) {String[] result = new String[1];result[0] = actions.getString(i);forward(result);}}public void close() throws HiveException {}
}

Hive 函数记录

1
动态分区默认最后一个字段为分区字段
自定义udtf组合可一行转多列
contat拼接2 NVL
NVL(表达式1,表达式2)
如果表达式1为空值,NVL返回值为表达式2的值,否则返回表达式1的值。
该函数的目的是把一个空值(null)转换成一个实际的值。其表达式的值可以是数字型、字符型和日期型。但是表达式1       和表达式2的数据类型必须为同一个类型。hive (gmall)> select nvl(1,0); 输出13 日期函数
date_format函数(根据格式整理日期)
hive (gmall)> select date_format('2020-06-14','yyyy-MM');date_add函数(加减日期)
hive (gmall)> select date_add('2020-06-14',-1);next_day函数 (取当前天的下一个周一)
hive (gmall)> select next_day('2020-06-14','MO');4 复杂数据函数
map结构数据定义 map<string,string>
array结构数据定义 array<string>
struct结构数据定义 struct<id:int,name:string,age:int>
struct和array嵌套定义 array<struct<id:int,name:string,age:int>>
例子
字段转map: str_to_map(concat_ws(',',collect_set(concat(order_status,'=',operate_time))),',','=')
转struct后转array collect_set(named_struct('page_id',page_id,'page_count',page_count,'during_time',during_time))
判断arry是否包含 if(array_contains(collect_set(is_new),'0'),'0','1')5 if
sum(if(dt=‘2020-06-14‘,count,0)) 如果dt符合要求则sum count字段值,否则sum 06 获取下一行数据 (lead获取下n行/lag获取上n行)
lead(page_id,1,null)over (partition by session_id order by ts)获取page_id下一行,如果没有取null7 case when
case when 条件1 then 结果1when 条件2 then 结果2
end7 一条sql同时计算最近1天,7天,30天的数据
将表数据通过explode三倍展开,对三个每份数据通过recent_days分别做计算,如下图

8 排序序号

DWS层设计


维度为基础的宽表汇总
如地区主题,每行记录一天的一个地区活跃用户的汇总记录总宽表
通过宽表,对应一个维度id,一天粒度的度量值汇总

另外可以不用full join方式,对子查询每个字段补0+union all子查询+group by的形式代替实现

DWT层设计

和DWS一样,维度为基础的宽表汇总
由一天转多个向前n天的度量值汇总,分区规则依然为1天一个文件


通过DWS表,昨天+今天数据减去7天/30天/n天等来实现DWT层的表,如下图

尚硅谷4.0数仓项目整体设计要点记录相关推荐

  1. 尚硅谷数据仓库实战之1项目需求及架构设计

    尚硅谷数据仓库实战之1项目需求及架构设计 第2章 项目需求及架构设计 需求分析 项目框架 技术选型 数据流程设计 框架版本选型 服务器选型 集群规模 集群资源规划设计 第3章 数据生成模块 目标数据 ...

  2. 【大数据数仓项目集群配置 一】

    本文用于记录我的第一次内网大数据集群配置过程. 本篇主要实现基础配置. 配置使用的软件版本和脚本参考自尚硅谷,链接如下: 链接: https://www.bilibili.com/video/BV1r ...

  3. 大数据千亿级离线数仓项目第一天 环境部署和etl

    千亿级数仓项目第01天讲义 课程目标 了解大数据离线数仓架构 了解项目部署环境(数据规模和集群规模) 掌握ETL工具 Kettle常用组件的使用 能够掌握kettle作业与转换区别以及linux部署 ...

  4. 尚硅谷 java基础第二个项目之客户关系管理系统

    尚硅谷 java基础第二个项目之客户关系管理系统. 做了一些完善,增加性别,电话,邮箱有效性验证.其中电话和邮箱验证直接"饮用"了网友的果汁. 在此感谢各位原著大佬们的分享. 具体 ...

  5. 本地数仓项目(二)——搭建系统业务数仓详细流程

    1 说明 本文基于<本地数据仓库项目(一)--本地数仓搭建详细流程>业务数据,在本地搭建系统业务数仓. 根据模拟sql脚本生成业务数据,依次执行生成业务数据即可. sql脚本提供如下 链接 ...

  6. CDH数仓项目(一) —— CDH安装部署搭建详细流程

    0 说明 本文以CDH搭建数据仓库,基于三台阿里云服务器从零开始搭建CDH集群,节点配置信息如下: 节点 内存 安装服务角色 chen102 16G cloudera-scm-server chen1 ...

  7. 本地数仓项目(四)—— 即席查询

    1 背景 本文描述本地数仓项目即席查询相关内容,主要涉及即席查询工具包括Presto.Druid.Kylin. 本文基于文章<本地数据仓库项目(一) -- 本地数仓搭建详细流程> 和< ...

  8. 尚硅谷Vue2.0+Vue3.0全套教程视频笔记 + 代码 [P001-050]

    视频链接:尚硅谷Vue2.0+Vue3.0全套教程丨vuejs从入门到精通_哔哩哔哩_bilibili P1-50:当前页面.  P51-100:尚硅谷Vue2.0+Vue3.0全套教程视频笔记 + ...

  9. 电商离线数仓项目实战(下)

    电商离线数仓项目实战(下) 电商分析--核心交易 文章目录 电商离线数仓项目实战(下) 电商分析--核心交易 一.业务需求 二.业务数据库表结构 1. 数据库表之间的联系 img 2. 业务数据库-- ...

最新文章

  1. Zabbix添加Ping外网IP监控
  2. pptv网络电视android,PP视频(原聚力视频)
  3. Android开发之The application could not be installed: INSTALL_FAILED_VERSION_DOWNGRADE报错
  4. 部署HDFS HA的环境
  5. 【转】01Teams的前世今生
  6. easy-ui实现左右滚动条
  7. [转载]遗留系统中的RUBY中文解决方案
  8. .net中使用TripleDESCryptoServiceProvider进行3DES加密遇到弱密钥的问题
  9. js代码在调试状态执行正确,但是正常使用时没有反应
  10. R语言 WDI包的使用
  11. 计算机excel表格教程高级筛选6,excel表格中的高级筛选要怎么操作?
  12. Fast Deep Matting for Portrait Animation on Mobile Phone
  13. 管外磁水处理器的简单介绍
  14. 【数据分析】基于时间序列的预测方法(2021-01-08)时间序列预测
  15. python的scrapy爬虫模块间进行传参_小猪的Python学习之旅 —— 4.Scrapy爬虫框架初体验...
  16. sequoia中的日志
  17. 对接天猫接口之如何授权订阅消息?包含天猫端授权和服务商端授权taobao.tmc.user.permit
  18. java 屏蔽广告js_用js屏蔽被http劫持的浮动广告实现方法
  19. Tailwind教程2 - 基础样式
  20. Linux服务器上使用nginx搭建mp4、flv流媒体服务器

热门文章

  1. python免费教程视频-Python视频教程免费下载,最新Python免费教程视频分享!
  2. hello.world程序的编写和运行
  3. python 手动清除内存gc
  4. IM3、IIP3、OIP3等的计算
  5. 如何使用Dinktopdf在.net core项目里将Html转成PDF
  6. 手机ai绘画软件哪个好?这些绘画软件值得你收藏
  7. h5 实现 画图 手写签批功能
  8. Angular获取当前路由
  9. UE4_如何渲染背景透明的物体
  10. 【计算机毕业设计】基于web的网上体育用品商城系统