黑马在线教育数仓实战5
5. 意向用户主题看板_全量流程
5.1 需求分析
主要分析什么内容:
1) 每一个需求涉及到那些维度, 那些直白
2) 每一个需求涉及到那些表, 表的字段
3) 找出需要进行清洗 转换的操作
4) 如果表涉及到多表, 需要找到表与表关联条件
- 需求一: 计期内,新增意向客户(包含自己录入的意向客户)总数。
涉及维度:
时间维度: 年 月 天 小时
新老维度
线上线下
涉及指标:
意向量涉及到表:
customer_relationship (客户意向表) (事实表)涉及到字段:
时间维度: create_date_time
此处有转换操作: 将时间转换为yearinfo, monthinfo, dayinfo, hourinfo
新老维度: ?
线上线下: ?
指标字段: customer_id
计算方案: 先去重在统计
说明: 无法在DWM层进行提前聚合
- 需求二: 统计指定时间段内,新增的意向客户,所在城市区域人数热力图。
涉及维度:
时间维度: 年 月 天 小时
新老维度:
地区维度:
线上线下
涉及指标:
意向量涉及表:
customer (客户表) (维度表)
customer_relationship(客户意向表) (事实表)涉及字段:
时间维度: 客户意向表.create_date_time
地区维度: 客户表.area
指标字段: 客户意向表.customer_id
表与表关联条件:
客户意向表.customer_id = 客户表.id
- 需求三: 统计指定时间段内,新增的意向客户中,意向学科人数排行榜。学科名称要关联查询出来。
涉及维度:
时间维度: 年 月 天 小时
新老维度:
学科维度:
线上线下:
涉及指标:
意向量涉及表:
customer_clue(客户线索表) (维度表)
customer_relationship(客户意向表) (事实表)
itcast_subject(学科表) (维度表)涉及字段:
时间维度:
客户意向表.create_date_time
新老维度:
客户线索表.clue_state
说明: 当字段的值为 'VALID_NEW_CLUES' 为新用户
暂定: 其他的值都是老用户
此处有转换: 将clue_state转换为clue_state_stat, 此新字段的值只有 0(老) 和 1(新)
线上线下维度:
客户意向表.origin_type
说明: 当字段的值为 'NETSERVICE' 或者 'PRESIGNUP' 表示为线上
暂定: 其他值都为线下
此处有转换: 将 origin_type 转换为 origin_type_stat 其中值只有 0(线下) 1(线上)
学科维度:
客户意向表.itcast_subject_id
学科.name
指标字段:
客户意向表.customer_id表与表关联条件:
客户意向表.itcast_subject_id = 学科表.id
客户线索表.customer_relationship_id = 客户意向表.id清洗操作:
客户线索表.deleted = false 数据保留下, 为true清洗掉
转换操作:
将学科id为 0 或者为 null的时候, 将其转换为 -1原则:
1) 事实表存在的字段 要优先使用, 如果没有从维度表中查询
2) 当维度出现二元(比如: 新 老, 线上 线下...)的维度的时候, 建议将其转换为 0 和 1来标记
- 需求四: 统计指定时间段内,新增的意向客户中,意向校区人数排行榜
涉及维度:
时间维度: 年 月 天 小时
新老维度:
校区维度:
线上线下:涉及指标:
意向量涉及表:
customer_clue(线索表)
customer_relationship(客户意向表)
itcast_school(校区表)
涉及字段:
新老维度: 线索表.clue_state (需要转换) --> clue_state_stat
线上线下: 客户意向表.origin_type(需要转换) --> origin_type_stat
时间维度: 客户意向表.create_date_time
校区维度:
客户意向表.itcast_school_id
校区表.name
指标字段:
客户意向表.customer_id清洗操作:
线索表.deleted = false
表与表关系:
客户意向表.itcast_school_id = 校区表.id
客户线索表.customer_relationship_id = 客户意向表.id转换操作:
将校区id为 0 或者为 null的时候, 将其转换为 -1
- 需求五: 统计指定时间段内,新增的意向客户中,不同来源渠道的意向客户占比。
涉及维度:
时间维度: 年 月 天 小时
新老维度:
来源渠道:
线上线下:涉及指标:
意向量涉及表:
customer_relationship(客户意向表)
customer_clue(线索表)
涉及字段:
新老维度: 线索表.clue_state (需要转换) --> clue_state_stat
线上线下: 客户意向表.origin_type(需要转换) --> origin_type_stat
时间维度: 客户意向表.create_date_time
来源渠道: 客户意向表.origin_type
指标字段:
客户意向表.customer_id
说明:
线上线下是各个来源渠道的上卷维度
清洗操作:
线索表.deleted = false表与表关联条件:
线索表.customer_relationship_id = 客户意向表.id
- 需求六: 统计指定时间段内,新增的意向客户中,各咨询中心产生的意向客户数占比情况。
涉及维度:
时间维度: 年 月 天 小时
新老维度:
各咨询中心维度:
线上线下维度:涉及指标:
意向量涉及表:
customer_relationship(客户意向表)
employee(员工表)
scrm_department(部门表)
customer_clue(线索表)
涉及字段:
新老维度: 线索表.clue_state (需要转换) --> clue_state_stat
线上线下: 客户意向表.origin_type(需要转换) --> origin_type_stat
时间维度: 客户意向表.create_date_time
各咨询中心:
员工表.tdepart_id
部门表.name
指标字段:
客户意向表.customer_id表与表的关联条件:
客户意向表.creator = 员工表.id
员工表.tdepart_id = 部门表.id
线索表.customer_relationship_id = 客户意向表.id
总结:
指标:
意向量维度:
固有维度:
时间维度: 年 月 天 小时
线上线下:
新老维度:
产品属性维度:
地区维度:
校区维度:
学科维度;
来源渠道:
各咨询中心涉及表:
customer_relationship(客户意向表) (事实表)
employee(员工表) (维度表)
scrm_department(部门表) (维度表)
customer_clue(线索表) (维度表)
itcast_school(校区表) (维度表)
itcast_subject(学科表) (维度表)
customer (客户表) (维度表)表与表关系:
客户意向表.creator = 员工表.id
员工表.tdepart_id = 部门表.id
线索表.customer_relationship_id = 客户意向表.id
客户意向表.itcast_school_id = 校区表.id
客户意向表.itcast_subject_id = 学科表.id
客户意向表.customer_id = 客户表.id涉及字段:
时间维度: 客户意向表.create_date_time
线上线下: 客户意向表.origin_type --> origin_type_stat
新老维度: 线索表.clue_state --> clue_state_stat
地区维度: 客户表.area
校区维度: 客户意向表.itcast_school_id 和 校区表.name
学科维度: 客户意向表.itcast_subject_id 和 学科表.name
来源渠道: 客户意向表.origin_type
各咨询中心: 员工表.tdepart_id 和 部门表.name
指标字段: 客户意向表.customer_id
清洗字段: 线索表.deleted需要清洗的内容: 将删除标记为true的数据删除
过滤出: 客户意向表.deleted = false需要转换的内容:
1) 日期: 客户意向表.create_date_time
需要转换为: yearinfo monthinfo dayinfo hourinfo
2) 新老维度: 线索表.clue_state
说明: 当字段的值为 'VALID_NEW_CLUES' 为新用户
暂定: 其他的值都是老用户
需要转换为一个新的字段: clue_state_stat
此字段只有二个值: 0(老) 1(新)
3) 线上线下: 客户意向表.origin_type
说明: 当字段的值为 'NETSERVICE' 或者 'PRESIGNUP' 表示为线上
暂定: 其他值都为线下
需要转换为一个新的字段: origin_type_stat
此字段只有二个值 0(线下) 1(线上)
4) 校区和学科的id转换
需要将客户意向表中, 校区id 和 学科id 如果为 0或者 null 转换为 -1
5.2 业务数据的准备工作
- 需要在mysql中创建一个库
create database scrm default character set utf8mb4 collate utf8mb4_unicode_ci;
- 将项目的业务数据集导入到这个库中
5.3 建模分析
- ODS层: 源数据层
- 作用: 对接数据源, 一般和数据源保持相同粒度 (直白: 将数据源中拷贝到ODS层中)
- 一般放置是事实表和少量的维度表
放置事实表即可:
customer_relationship(意向表 ) -- 本次主题的事实表
customer_clue(线索表) -- 本次主题的维度表, 下次主题的事实表
建表操作:
表中字段与数据源中字段保持一致, 只需要多加一个 抽取时间的字段即可
请注意:
意向表 和 线索表中数据存在数据变更操作,需要采用缓慢渐变维的方式来解决
- DIM层: 数据维度层
放置维度表:
5张表
customer(客户表) --- 维度表
itcast_subject(学科表) --- 维度表
itcast_school(校区表) --- 维度表
employee(员工表) --- 维度表
scrm_department(部门表) --- 维度表建表:
与数据源保持一致的字段即可, 多加一个 抽取时间的字段
DW层: 数据仓库层
DWD层: 数据明细层
- 作用: 1) 清洗转换处理工作 2) 少量维度退化(此层不需要执行)
需要清洗内容:
将标记为删除的数据进行过滤掉需要转换内容:
1) 将create_date_time 转换为 yearinfo monthinfo dayinfo hourinfo
2) 将origin_type 转换为 origin_type_state (用于统计线上线下)
转换逻辑: origin_type的值为: NETSERVICE 或者 PRESIGNUP 认为线上 其余认为线下
3) 将clue_state 转换为 clue_state_stat (用于统计新老维度)
转换逻辑:clue_state的值为 VALID_NEW_CLUES 为新客户 其余暂定为老客户
4) 将校区和学科的 id字段, 如果为 0 或者 null 转换为 -1
- 建模内容
DWD层表的构建: 必须字段(只能是事实表中字段) + 清洗的字段 + 转换的字段+ join字段
customer_relationship(意向表 ) --- 事实表
时间维度: create_date_time
线上线下: origin_type --> origin_type_stat
来源渠道: origin_type
校区维度: itcast_school_id
学科维度: itcast_subject_id
指标字段: customer_id,
关联条件的字段: creator,id表字段的组成:
customer_id, create_date_time,origin_type,itcast_school_id,itcast_subject_id,creator,id
deleted,origin_type_stat,yearinfo monthinfo dayinfo hourinfo
- 作用: 1) 清洗转换处理工作 2) 少量维度退化(此层不需要执行)
DWM层: 数据中间层
- 作用: 1) 提前聚合的操作( 由于有去重,导致无法实施) 2) 维度退化操作
此层后期处理的时候, 需要进行七表关联的操作
DWM层表的构建: 指标字段 + 各个表维度相关的字段
维度:
固有维度:
时间维度: 年 月 天 小时
新老维度:
线上线下产品属性维度:
总意向量
地区(区域)维度
学科维度
校区维度
来源渠道
各咨询中心DWM表的字段:
customer_id,
create_date_time, yearinfo monthinfo dayinfo hourinfo
deleted (意义不大)
clue_state_stat(此字段需要转换)
origin_type_stat
area,
itcast_subject_id,itcast_subject_name
itcast_school_id,itcast_school_name
origin_type
tdepart_id,tdepart_name
DWS层: 数据业务层
- 作用: 细化统计各个维度的数据
DWS层表字段构成: 统计的字段 + 各个维度的字段 + 三个用于查询的字段
维度:
固有维度:
时间维度: 年 月 天 小时
新老维度:
线上线下产品属性维度:
总意向量
地区(区域)维度
学科维度
校区维度
来源渠道
各咨询中心DWS层表字段:
customerid_total,
yearinfo,monthinfo,dayinfo,hourinfo
clue_state_stat,
origin_type_stat,
area
itcast_subject_id,itcast_subject_name
itcast_school_id,itcast_school_name
origin_type
tdepart_id,tdepart_name
group_type
time_type
time_str
- 作用: 细化统计各个维度的数据
DA层: 数据应用层
- 此层不需要
5.4 分桶表优化方案:
思考: 什么是分桶表?
主要是用于分文件的, 在建表的时候, 指定按照那些字段执行分桶操作, 并可以设置需要分多少个桶, 当插入数据的时候, 执行MR的分区的操作, 将数据分散各个分区(hive分桶)中, 默认分发方案: hash 取模
如何构建一个分桶表呢?
create table test_buck(id int, name string)
clustered by(id) sorted by (id asc) into 6 buckets -- 创建分桶表的SQL
row format delimited fields terminated by '\t';
如何向分桶表添加数据呢?
标准格式:
1) 创建一张与分桶表一样的临时表,唯一区别这个表不是一个分桶表
2) 将数据加载到这个临时表中
3) 通过 insert into + select 语句将数据导入到分桶表中说明: sqoop不支持直接对分桶表导入数据
分桶表有什么作用呢?
1) 进行数据采样
案例1: 数据质量校验工作(一般会先判断各个字段数据的结构信息是否完整)
案例2: 在进行数据分析的时候, 一天需要编写N多条SQL, 但是每编写一条SQL后, 都需要对SQL做一个校验, 如果直接面对完整的数据集做校验, 会导致校验时间过长, 影响开发进度, 此时可以先采样出一部分数据
案例3: 在计算一些比率值,或者 在计算相对指标的时候, 也会基于采样数据来计算相对指标
比如: 计算当前月的销售额相对上个月 环比增长了百分之多少?
可以选择当前月和上个月抽取出百分之30的数据, 基于这个数据来计算
2) 提升查询的效率(单表|多表)
5.4.1 如何进行数据采样
- 采样函数
tablesample(bucket x out of y on column)
采样函数:
tablesample(bucket x out of y on column)放置位置: 紧紧放置表的后面 如果表有别名 必须放置别名的前面
说明:
x: 从第几个桶开始进行采样
y: 抽样比例(总桶数/y=分多少个桶)
column: 分桶的字段, 可以省略的注意:
x 不能大于 y
y 必须是表的分桶数量的倍数或者因子案例:
1) 假设 A表有10个桶, 请分析, 下面的采样函数, 会将那些桶抽取出来
tablesample(bucket 2 out of 5 on xxx)会抽取几个桶呢? 总桶 / y = 分桶数量 2
抽取第几个编号的桶? (x+y)
2,7
2) 假设 A表有20个桶, 请分析, 下面的采样函数, 会将那些桶抽取出来
tablesample(bucket 4 out of 4 on xxx)会抽取几个桶呢? 总桶 / y = 分桶数量 5
抽取第几个编号的桶? (x+y)
4,8,12,16,20
5.4.2 如何提升查询的效率
对于单表效率的提升, 已经在前面讲过了, 这里不再讲解....
以下主要来讲解, 关于多表的效率的提升
思考: 当多表进行join的时候, 如何提升join效率呢?
reduce端join的流程:
可能出现的问题:
1) 可能出现数据倾斜的问题
2) 导致reduce压力较大
小表和大表:
- 采用 map join的方案
在进行join的时候, 将小表的数据放置到每一个读取大表的mapTask的内存中, 让mapTask每读取一次大表的数据都和内存中小表的数据进行join操作, 将join上的结果输出到reduce端即可, 从而实现在map端完成join的操作
如何开启map Joinset hive.auto.convert.join=true; -- 是否开启map Joinset hive.auto.convert.join.noconditionaltask.size=512000000; -- 设置小表最大的阈值(设置block cache 缓存大小)map Join 不限制任何表
中型表和大表:
中型表: 与小表相比 大约是小表3~10倍左右
解决方案:
- 能提前过滤就提前过滤掉(一旦提前过滤后, 会导致中型表的数据量会下降, 有可能达到小表阈值)
- 如果join的字段值有大量的null, 可以尝试添加随机数(保证各个reduce接收数据量差不多的, 减少数据倾斜问题)
- 基于分桶表的: bucket map join
bucket map join的生效条件:
1) set hive.optimize.bucketmapjoin = true; --开启bucket map join 支持
2) 一个表的bucket数是另一个表bucket数的整数倍
3) bucket列 == join列
4) 必须是应用在map join的场景中注意:如果表不是bucket的,则只是做普通join。
大表和大表:
解决方案:
- 能提前过滤就提前过滤掉(减少join之间的数量, 提升reduce执行效率)
- 如果join的字段值有大量的null, 可以尝试添加随机数(保证各个reduce接收数据量差不多的, 减少数据倾斜问题)
- SMB Map join (sort merge bucket map join)
实现SMB map join的条件要求:
1) 一个表的bucket数等于另一个表bucket数(分桶数量是一致)
2) bucket列 == join列 == sort 列
3) 必须是应用在bucket map join的场景中
4) 开启相关的参数:
-- 开启SMB map join
set hive.auto.convert.sortmerge.join=true;
set hive.auto.convert.sortmerge.join.noconditionaltask=true;
--写入数据强制排序
set hive.enforce.sorting=true;
set hive.optimize.bucketmapjoin.sortedmerge = true; -- 开启自动尝试SMB连接
5.5 建模操作
- ODS层:
set hive.exec.orc.compression.strategy=COMPRESSION;
-- 客户意向表(内部 分区 分桶表, 拉链表)
CREATE TABLE IF NOT EXISTS itcast_ods.`customer_relationship` (`id` int COMMENT '客户关系id',`create_date_time` STRING COMMENT '创建时间',`update_date_time` STRING COMMENT '最后更新时间',`deleted` int COMMENT '是否被删除(禁用)',`customer_id` int COMMENT '所属客户id',`first_id` int COMMENT '第一条客户关系id',`belonger` int COMMENT '归属人',`belonger_name` STRING COMMENT '归属人姓名',`initial_belonger` int COMMENT '初始归属人',`distribution_handler` int COMMENT '分配处理人',`business_scrm_department_id` int COMMENT '归属部门',`last_visit_time` STRING COMMENT '最后回访时间',`next_visit_time` STRING COMMENT '下次回访时间',`origin_type` STRING COMMENT '数据来源',`itcast_school_id` int COMMENT '校区Id',`itcast_subject_id` int COMMENT '学科Id',`intention_study_type` STRING COMMENT '意向学习方式',`anticipat_signup_date` STRING COMMENT '预计报名时间',`level` STRING COMMENT '客户级别',`creator` int COMMENT '创建人',`current_creator` int COMMENT '当前创建人:初始==创建人,当在公海拉回时为 拉回人',`creator_name` STRING COMMENT '创建者姓名',`origin_channel` STRING COMMENT '来源渠道',`comment` STRING COMMENT '备注',`first_customer_clue_id` int COMMENT '第一条线索id',`last_customer_clue_id` int COMMENT '最后一条线索id',`process_state` STRING COMMENT '处理状态',`process_time` STRING COMMENT '处理状态变动时间',`payment_state` STRING COMMENT '支付状态',`payment_time` STRING COMMENT '支付状态变动时间',`signup_state` STRING COMMENT '报名状态',`signup_time` STRING COMMENT '报名时间',`notice_state` STRING COMMENT '通知状态',`notice_time` STRING COMMENT '通知状态变动时间',`lock_state` STRING COMMENT '锁定状态',`lock_time` STRING COMMENT '锁定状态修改时间',`itcast_clazz_id` int COMMENT '所属ems班级id',`itcast_clazz_time` STRING COMMENT '报班时间',`payment_url` STRING COMMENT '付款链接',`payment_url_time` STRING COMMENT '支付链接生成时间',`ems_student_id` int COMMENT 'ems的学生id',`delete_reason` STRING COMMENT '删除原因',`deleter` int COMMENT '删除人',`deleter_name` STRING COMMENT '删除人姓名',`delete_time` STRING COMMENT '删除时间',`course_id` int COMMENT '课程ID',`course_name` STRING COMMENT '课程名称',`delete_comment` STRING COMMENT '删除原因说明',`close_state` STRING COMMENT '关闭装填',`close_time` STRING COMMENT '关闭状态变动时间',`appeal_id` int COMMENT '申诉id',`tenant` int COMMENT '租户',`total_fee` DECIMAL COMMENT '报名费总金额',`belonged` int COMMENT '小周期归属人',`belonged_time` STRING COMMENT '归属时间',`belonger_time` STRING COMMENT '归属时间',`transfer` int COMMENT '转移人',`transfer_time` STRING COMMENT '转移时间',`follow_type` int COMMENT '分配类型,0-自动分配,1-手动分配,2-自动转移,3-手动单个转移,4-手动批量转移,5-公海领取',`transfer_bxg_oa_account` STRING COMMENT '转移到博学谷归属人OA账号',`transfer_bxg_belonger_name` STRING COMMENT '转移到博学谷归属人OA姓名',`end_time` STRING COMMENT '有效截止时间')
comment '客户关系表'
PARTITIONED BY(start_time STRING)
clustered by(id) sorted by(id) into 10 buckets
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
TBLPROPERTIES ('orc.compress'='ZLIB');-- 客户线索表: (内部分区分桶表, 拉链表)
CREATE TABLE IF NOT EXISTS itcast_ods.customer_clue (id int COMMENT 'customer_clue_id',create_date_time STRING COMMENT '创建时间',update_date_time STRING COMMENT '最后更新时间',deleted STRING COMMENT '是否被删除(禁用)',customer_id int COMMENT '客户id',customer_relationship_id int COMMENT '客户关系id',session_id STRING COMMENT '七陌会话id',sid STRING COMMENT '访客id',status STRING COMMENT '状态(undeal待领取 deal 已领取 finish 已关闭 changePeer 已流转)',users STRING COMMENT '所属坐席',create_time STRING COMMENT '七陌创建时间',platform STRING COMMENT '平台来源 (pc-网站咨询|wap-wap咨询|sdk-app咨询|weixin-微信咨询)',s_name STRING COMMENT '用户名称',seo_source STRING COMMENT '搜索来源',seo_keywords STRING COMMENT '关键字',ip STRING COMMENT 'IP地址',referrer STRING COMMENT '上级来源页面',from_url STRING COMMENT '会话来源页面',landing_page_url STRING COMMENT '访客着陆页面',url_title STRING COMMENT '咨询页面title',to_peer STRING COMMENT '所属技能组',manual_time STRING COMMENT '人工开始时间',begin_time STRING COMMENT '坐席领取时间 ',reply_msg_count int COMMENT '客服回复消息数',total_msg_count int COMMENT '消息总数',msg_count int COMMENT '客户发送消息数',comment STRING COMMENT '备注',finish_reason STRING COMMENT '结束类型',finish_user STRING COMMENT '结束坐席',end_time STRING COMMENT '会话结束时间',platform_description STRING COMMENT '客户平台信息',browser_name STRING COMMENT '浏览器名称',os_info STRING COMMENT '系统名称',area STRING COMMENT '区域',country STRING COMMENT '所在国家',province STRING COMMENT '省',city STRING COMMENT '城市',creator int COMMENT '创建人',name STRING COMMENT '客户姓名',idcard STRING COMMENT '身份证号',phone STRING COMMENT '手机号',itcast_school_id int COMMENT '校区Id',itcast_school STRING COMMENT '校区',itcast_subject_id int COMMENT '学科Id',itcast_subject STRING COMMENT '学科',wechat STRING COMMENT '微信',qq STRING COMMENT 'qq号',email STRING COMMENT '邮箱',gender STRING COMMENT '性别',level STRING COMMENT '客户级别',origin_type STRING COMMENT '数据来源渠道',information_way STRING COMMENT '资讯方式',working_years STRING COMMENT '开始工作时间',technical_directions STRING COMMENT '技术方向',customer_state STRING COMMENT '当前客户状态',valid STRING COMMENT '该线索是否是网资有效线索',anticipat_signup_date STRING COMMENT '预计报名时间',clue_state STRING COMMENT '线索状态',scrm_department_id int COMMENT 'SCRM内部部门id',superior_url STRING COMMENT '诸葛获取上级页面URL',superior_source STRING COMMENT '诸葛获取上级页面URL标题',landing_url STRING COMMENT '诸葛获取着陆页面URL',landing_source STRING COMMENT '诸葛获取着陆页面URL来源',info_url STRING COMMENT '诸葛获取留咨页URL',info_source STRING COMMENT '诸葛获取留咨页URL标题',origin_channel STRING COMMENT '投放渠道',course_id int COMMENT '课程编号',course_name STRING COMMENT '课程名称',zhuge_session_id STRING COMMENT 'zhuge会话id',is_repeat int COMMENT '是否重复线索(手机号维度) 0:正常 1:重复',tenant int COMMENT '租户id',activity_id STRING COMMENT '活动id',activity_name STRING COMMENT '活动名称',follow_type int COMMENT '分配类型,0-自动分配,1-手动分配,2-自动转移,3-手动单个转移,4-手动批量转移,5-公海领取',shunt_mode_id int COMMENT '匹配到的技能组id',shunt_employee_group_id int COMMENT '所属分流员工组',ends_time STRING COMMENT '有效时间')
comment '客户关系表'
PARTITIONED BY(starts_time STRING)
clustered by(customer_relationship_id) sorted by(customer_relationship_id) into 10 buckets
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
TBLPROPERTIES ('orc.compress'='ZLIB');
- DIM层:
CREATE DATABASE IF NOT EXISTS itcast_dimen;
-- 客户表
CREATE TABLE IF NOT EXISTS itcast_dimen.`customer` (`id` int COMMENT 'key id',`customer_relationship_id` int COMMENT '当前意向id',`create_date_time` STRING COMMENT '创建时间',`update_date_time` STRING COMMENT '最后更新时间',`deleted` int COMMENT '是否被删除(禁用)',`name` STRING COMMENT '姓名',`idcard` STRING COMMENT '身份证号',`birth_year` int COMMENT '出生年份',`gender` STRING COMMENT '性别',`phone` STRING COMMENT '手机号',`wechat` STRING COMMENT '微信',`qq` STRING COMMENT 'qq号',`email` STRING COMMENT '邮箱',`area` STRING COMMENT '所在区域',`leave_school_date` date COMMENT '离校时间',`graduation_date` date COMMENT '毕业时间',`bxg_student_id` STRING COMMENT '博学谷学员ID,可能未关联到,不存在',`creator` int COMMENT '创建人ID',`origin_type` STRING COMMENT '数据来源',`origin_channel` STRING COMMENT '来源渠道',`tenant` int,`md_id` int COMMENT '中台id')
comment '客户表'
PARTITIONED BY(start_time STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
TBLPROPERTIES ('orc.compress'='SNAPPY');-- 学科表
CREATE TABLE IF NOT EXISTS itcast_dimen.`itcast_subject` (`id` int COMMENT '自增主键',`create_date_time` timestamp COMMENT '创建时间',`update_date_time` timestamp COMMENT '最后更新时间',`deleted` STRING COMMENT '是否被删除(禁用)',`name` STRING COMMENT '学科名称',`code` STRING COMMENT '学科编码',`tenant` int COMMENT '租户')
comment '学科字典表'
PARTITIONED BY(start_time STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
TBLPROPERTIES ('orc.compress'='SNAPPY');-- 校区表
CREATE TABLE IF NOT EXISTS itcast_dimen.`itcast_school` (`id` int COMMENT '自增主键',`create_date_time` timestamp COMMENT '创建时间',`update_date_time` timestamp COMMENT '最后更新时间',`deleted` STRING COMMENT '是否被删除(禁用)',`name` STRING COMMENT '校区名称',`code` STRING COMMENT '校区标识',`tenant` int COMMENT '租户')
comment '校区字典表'
PARTITIONED BY(start_time STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
TBLPROPERTIES ('orc.compress'='SNAPPY');-- 员工表
CREATE TABLE IF NOT EXISTS itcast_dimen.employee (id int COMMENT '员工id',email STRING COMMENT '公司邮箱,OA登录账号',real_name STRING COMMENT '员工的真实姓名',phone STRING COMMENT '手机号,目前还没有使用;隐私问题OA接口没有提供这个属性,',department_id STRING COMMENT 'OA中的部门编号,有负值',department_name STRING COMMENT 'OA中的部门名',remote_login STRING COMMENT '员工是否可以远程登录',job_number STRING COMMENT '员工工号',cross_school STRING COMMENT '是否有跨校区权限',last_login_date STRING COMMENT '最后登录日期',creator int COMMENT '创建人',create_date_time STRING COMMENT '创建时间',update_date_time STRING COMMENT '最后更新时间',deleted STRING COMMENT '是否被删除(禁用)',scrm_department_id int COMMENT 'SCRM内部部门id',leave_office STRING COMMENT '离职状态',leave_office_time STRING COMMENT '离职时间',reinstated_time STRING COMMENT '复职时间',superior_leaders_id int COMMENT '上级领导ID',tdepart_id int COMMENT '直属部门',tenant int COMMENT '租户',ems_user_name STRING COMMENT 'ems用户名称'
)
comment '员工表'
PARTITIONED BY(start_time STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
TBLPROPERTIES ('orc.compress'='SNAPPY');-- 部门表
CREATE TABLE IF NOT EXISTS itcast_dimen.`scrm_department` (`id` int COMMENT '部门id',`name` STRING COMMENT '部门名称',`parent_id` int COMMENT '父部门id',`create_date_time` STRING COMMENT '创建时间',`update_date_time` STRING COMMENT '更新时间',`deleted` STRING COMMENT '删除标志',`id_path` STRING COMMENT '编码全路径',`tdepart_code` int COMMENT '直属部门',`creator` STRING COMMENT '创建者',`depart_level` int COMMENT '部门层级',`depart_sign` int COMMENT '部门标志,暂时默认1',`depart_line` int COMMENT '业务线,存储业务线编码',`depart_sort` int COMMENT '排序字段',`disable_flag` int COMMENT '禁用标志',`tenant` int COMMENT '租户')
comment 'scrm部门表'
PARTITIONED BY(start_time STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
TBLPROPERTIES ('orc.compress'='SNAPPY');
- DWD层
CREATE TABLE IF NOT EXISTS itcast_dwd.`itcast_intention_dwd` (`rid` int COMMENT 'id',`customer_id` STRING COMMENT '客户id',`create_date_time` STRING COMMENT '创建时间',`itcast_school_id` STRING COMMENT '校区id',`deleted` STRING COMMENT '是否被删除',`origin_type` STRING COMMENT '来源渠道',`itcast_subject_id` STRING COMMENT '学科id',`creator` int COMMENT '创建人',`hourinfo` STRING COMMENT '小时信息',`origin_type_stat` STRING COMMENT '数据来源:0.线下;1.线上'
)
comment '客户意向dwd表'
PARTITIONED BY(yearinfo STRING,monthinfo STRING,dayinfo STRING)
clustered by(rid) sorted by(rid) into 10 buckets
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as ORC
TBLPROPERTIES ('orc.compress'='SNAPPY');
- DWM层:
create database itcast_dwm;CREATE TABLE IF NOT EXISTS itcast_dwm.`itcast_intention_dwm` (`customer_id` STRING COMMENT 'id信息',`create_date_time` STRING COMMENT '创建时间',`area` STRING COMMENT '区域信息',`itcast_school_id` STRING COMMENT '校区id',`itcast_school_name` STRING COMMENT '校区名称',`deleted` STRING COMMENT '是否被删除',`origin_type` STRING COMMENT '来源渠道',`itcast_subject_id` STRING COMMENT '学科id',`itcast_subject_name` STRING COMMENT '学科名称',`hourinfo` STRING COMMENT '小时信息',`origin_type_stat` STRING COMMENT '数据来源:0.线下;1.线上',`clue_state_stat` STRING COMMENT '新老客户:0.老客户;1.新客户',`tdepart_id` STRING COMMENT '创建者部门id',`tdepart_name` STRING COMMENT '咨询中心名称'
)
comment '客户意向dwm表'
PARTITIONED BY(yearinfo STRING,monthinfo STRING,dayinfo STRING)
clustered by(customer_id) sorted by(customer_id) into 10 buckets
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as ORC
TBLPROPERTIES ('orc.compress'='SNAPPY');
- DWS层:
CREATE TABLE IF NOT EXISTS itcast_dws.itcast_intention_dws (`customer_total` INT COMMENT '聚合意向客户数',`area` STRING COMMENT '区域信息',`itcast_school_id` STRING COMMENT '校区id',`itcast_school_name` STRING COMMENT '校区名称',`origin_type` STRING COMMENT '来源渠道',`itcast_subject_id` STRING COMMENT '学科id',`itcast_subject_name` STRING COMMENT '学科名称',`hourinfo` STRING COMMENT '小时信息',`origin_type_stat` STRING COMMENT '数据来源:0.线下;1.线上',`clue_state_stat` STRING COMMENT '客户属性:0.老客户;1.新客户',`tdepart_id` STRING COMMENT '创建者部门id',`tdepart_name` STRING COMMENT '咨询中心名称',`time_str` STRING COMMENT '时间明细',`groupType` STRING COMMENT '产品属性类别:1.总意向量;2.区域信息;3.校区、学科组合分组;4.来源渠道;5.咨询中心;',`time_type` STRING COMMENT '时间维度:1、按小时聚合;2、按天聚合;3、按周聚合;4、按月聚合;5、按年聚合;'
)
comment '客户意向dws表'
PARTITIONED BY(yearinfo STRING,monthinfo STRING,dayinfo STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
TBLPROPERTIES ('orc.compress'='SNAPPY');
5.6 数据采集
指的: 将业务库中的数据一对一导入到ODS层的对应表中
业务库: mysql
ODS层: hive技术: 使用apache sqoop
- DIM层:
# 客户表
sqoop import \
--connect jdbc:mysql://192.168.52.150:3306/scrm \
--username root \
--password 123456 \
--query 'SELECT *, "2021-09-27" AS start_time
FROM customer where 1=1 and $CONDITIONS' \
--hcatalog-database itcast_dimen \
--hcatalog-table customer \
-m 1 # 学科表:
sqoop import \
--connect jdbc:mysql://192.168.52.150:3306/scrm \
--username root \
--password 123456 \
--query 'SELECT *, "2021-09-27" AS start_time
FROM itcast_subject where 1=1 and $CONDITIONS' \
--hcatalog-database itcast_dimen \
--hcatalog-table itcast_subject \
-m 1 # 校区表:
sqoop import \
--connect jdbc:mysql://192.168.52.150:3306/scrm \
--username root \
--password 123456 \
--query 'SELECT *, "2021-09-27" AS start_time
FROM itcast_school where 1=1 and $CONDITIONS' \
--hcatalog-database itcast_dimen \
--hcatalog-table itcast_school \
-m 1 # 员工表
sqoop import \
--connect jdbc:mysql://192.168.52.150:3306/scrm \
--username root \
--password 123456 \
--query 'SELECT *, "2021-09-27" AS start_time
FROM employee where 1=1 and $CONDITIONS' \
--hcatalog-database itcast_dimen \
--hcatalog-table employee \
-m 1# 部门表
sqoop import \
--connect jdbc:mysql://192.168.52.150:3306/scrm \
--username root \
--password 123456 \
--query 'SELECT *, "2021-09-27" AS start_time
FROM scrm_department where 1=1 and $CONDITIONS' \
--hcatalog-database itcast_dimen \
--hcatalog-table scrm_department \
-m 1
- ODS层:
-- 客户意向表
-- 第一步: 创建一张客户意向表的临时表
CREATE TABLE IF NOT EXISTS itcast_ods.`customer_relationship_temp` (`id` int COMMENT '客户关系id',`create_date_time` STRING COMMENT '创建时间',`update_date_time` STRING COMMENT '最后更新时间',`deleted` int COMMENT '是否被删除(禁用)',`customer_id` int COMMENT '所属客户id',`first_id` int COMMENT '第一条客户关系id',`belonger` int COMMENT '归属人',`belonger_name` STRING COMMENT '归属人姓名',`initial_belonger` int COMMENT '初始归属人',`distribution_handler` int COMMENT '分配处理人',`business_scrm_department_id` int COMMENT '归属部门',`last_visit_time` STRING COMMENT '最后回访时间',`next_visit_time` STRING COMMENT '下次回访时间',`origin_type` STRING COMMENT '数据来源',`itcast_school_id` int COMMENT '校区Id',`itcast_subject_id` int COMMENT '学科Id',`intention_study_type` STRING COMMENT '意向学习方式',`anticipat_signup_date` STRING COMMENT '预计报名时间',`level` STRING COMMENT '客户级别',`creator` int COMMENT '创建人',`current_creator` int COMMENT '当前创建人:初始==创建人,当在公海拉回时为 拉回人',`creator_name` STRING COMMENT '创建者姓名',`origin_channel` STRING COMMENT '来源渠道',`comment` STRING COMMENT '备注',`first_customer_clue_id` int COMMENT '第一条线索id',`last_customer_clue_id` int COMMENT '最后一条线索id',`process_state` STRING COMMENT '处理状态',`process_time` STRING COMMENT '处理状态变动时间',`payment_state` STRING COMMENT '支付状态',`payment_time` STRING COMMENT '支付状态变动时间',`signup_state` STRING COMMENT '报名状态',`signup_time` STRING COMMENT '报名时间',`notice_state` STRING COMMENT '通知状态',`notice_time` STRING COMMENT '通知状态变动时间',`lock_state` STRING COMMENT '锁定状态',`lock_time` STRING COMMENT '锁定状态修改时间',`itcast_clazz_id` int COMMENT '所属ems班级id',`itcast_clazz_time` STRING COMMENT '报班时间',`payment_url` STRING COMMENT '付款链接',`payment_url_time` STRING COMMENT '支付链接生成时间',`ems_student_id` int COMMENT 'ems的学生id',`delete_reason` STRING COMMENT '删除原因',`deleter` int COMMENT '删除人',`deleter_name` STRING COMMENT '删除人姓名',`delete_time` STRING COMMENT '删除时间',`course_id` int COMMENT '课程ID',`course_name` STRING COMMENT '课程名称',`delete_comment` STRING COMMENT '删除原因说明',`close_state` STRING COMMENT '关闭装填',`close_time` STRING COMMENT '关闭状态变动时间',`appeal_id` int COMMENT '申诉id',`tenant` int COMMENT '租户',`total_fee` DECIMAL COMMENT '报名费总金额',`belonged` int COMMENT '小周期归属人',`belonged_time` STRING COMMENT '归属时间',`belonger_time` STRING COMMENT '归属时间',`transfer` int COMMENT '转移人',`transfer_time` STRING COMMENT '转移时间',`follow_type` int COMMENT '分配类型,0-自动分配,1-手动分配,2-自动转移,3-手动单个转移,4-手动批量转移,5-公海领取',`transfer_bxg_oa_account` STRING COMMENT '转移到博学谷归属人OA账号',`transfer_bxg_belonger_name` STRING COMMENT '转移到博学谷归属人OA姓名',`end_time` STRING COMMENT '有效截止时间')
comment '客户关系表'
PARTITIONED BY(start_time STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
TBLPROPERTIES ('orc.compress'='ZLIB');-- 第二步: 编写sqoop命令 将数据导入到临时表
sqoop import \
--connect jdbc:mysql://192.168.52.150:3306/scrm \
--username root \
--password 123456 \
--query 'SELECT *, "9999-12-31" as end_time , "2021-09-27" AS start_time
FROM customer_relationship where 1=1 and $CONDITIONS' \
--hcatalog-database itcast_ods \
--hcatalog-table customer_relationship_temp \
-m 1-- 第三步: 执行 insert into + select 导入到目标表
-- 动态分区配置
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
-- hive压缩
set hive.exec.compress.intermediate=true;
set hive.exec.compress.output=true;
-- 写入时压缩生效
set hive.exec.orc.compression.strategy=COMPRESSION;insert into table itcast_ods.customer_relationship partition(start_time)
select * from itcast_ods.customer_relationship_temp;
客户线索表
-- 第一步: 创建客户线索表的临时表
CREATE TABLE IF NOT EXISTS itcast_ods.customer_clue_temp (id int COMMENT 'customer_clue_id',create_date_time STRING COMMENT '创建时间',update_date_time STRING COMMENT '最后更新时间',deleted STRING COMMENT '是否被删除(禁用)',customer_id int COMMENT '客户id',customer_relationship_id int COMMENT '客户关系id',session_id STRING COMMENT '七陌会话id',sid STRING COMMENT '访客id',status STRING COMMENT '状态(undeal待领取 deal 已领取 finish 已关闭 changePeer 已流转)',users STRING COMMENT '所属坐席',create_time STRING COMMENT '七陌创建时间',platform STRING COMMENT '平台来源 (pc-网站咨询|wap-wap咨询|sdk-app咨询|weixin-微信咨询)',s_name STRING COMMENT '用户名称',seo_source STRING COMMENT '搜索来源',seo_keywords STRING COMMENT '关键字',ip STRING COMMENT 'IP地址',referrer STRING COMMENT '上级来源页面',from_url STRING COMMENT '会话来源页面',landing_page_url STRING COMMENT '访客着陆页面',url_title STRING COMMENT '咨询页面title',to_peer STRING COMMENT '所属技能组',manual_time STRING COMMENT '人工开始时间',begin_time STRING COMMENT '坐席领取时间 ',reply_msg_count int COMMENT '客服回复消息数',total_msg_count int COMMENT '消息总数',msg_count int COMMENT '客户发送消息数',comment STRING COMMENT '备注',finish_reason STRING COMMENT '结束类型',finish_user STRING COMMENT '结束坐席',end_time STRING COMMENT '会话结束时间',platform_description STRING COMMENT '客户平台信息',browser_name STRING COMMENT '浏览器名称',os_info STRING COMMENT '系统名称',area STRING COMMENT '区域',country STRING COMMENT '所在国家',province STRING COMMENT '省',city STRING COMMENT '城市',creator int COMMENT '创建人',name STRING COMMENT '客户姓名',idcard STRING COMMENT '身份证号',phone STRING COMMENT '手机号',itcast_school_id int COMMENT '校区Id',itcast_school STRING COMMENT '校区',itcast_subject_id int COMMENT '学科Id',itcast_subject STRING COMMENT '学科',wechat STRING COMMENT '微信',qq STRING COMMENT 'qq号',email STRING COMMENT '邮箱',gender STRING COMMENT '性别',level STRING COMMENT '客户级别',origin_type STRING COMMENT '数据来源渠道',information_way STRING COMMENT '资讯方式',working_years STRING COMMENT '开始工作时间',technical_directions STRING COMMENT '技术方向',customer_state STRING COMMENT '当前客户状态',valid STRING COMMENT '该线索是否是网资有效线索',anticipat_signup_date STRING COMMENT '预计报名时间',clue_state STRING COMMENT '线索状态',scrm_department_id int COMMENT 'SCRM内部部门id',superior_url STRING COMMENT '诸葛获取上级页面URL',superior_source STRING COMMENT '诸葛获取上级页面URL标题',landing_url STRING COMMENT '诸葛获取着陆页面URL',landing_source STRING COMMENT '诸葛获取着陆页面URL来源',info_url STRING COMMENT '诸葛获取留咨页URL',info_source STRING COMMENT '诸葛获取留咨页URL标题',origin_channel STRING COMMENT '投放渠道',course_id int COMMENT '课程编号',course_name STRING COMMENT '课程名称',zhuge_session_id STRING COMMENT 'zhuge会话id',is_repeat int COMMENT '是否重复线索(手机号维度) 0:正常 1:重复',tenant int COMMENT '租户id',activity_id STRING COMMENT '活动id',activity_name STRING COMMENT '活动名称',follow_type int COMMENT '分配类型,0-自动分配,1-手动分配,2-自动转移,3-手动单个转移,4-手动批量转移,5-公海领取',shunt_mode_id int COMMENT '匹配到的技能组id',shunt_employee_group_id int COMMENT '所属分流员工组',ends_time STRING COMMENT '有效时间')
comment '客户关系表'
PARTITIONED BY(starts_time STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
TBLPROPERTIES ('orc.compress'='ZLIB');-- 第二步: 编写sqoop命令 将数据导入到临时表
sqoop import \
--connect jdbc:mysql://192.168.52.150:3306/scrm \
--username root \
--password 123456 \
--query 'SELECT id,create_date_time,update_date_time,deleted,customer_id,customer_relationship_id,session_id,sid,status,user as users,create_time,platform,s_name,seo_source,seo_keywords,ip,referrer,from_url,landing_page_url,url_title,to_peer,manual_time,begin_time,reply_msg_count,total_msg_count,msg_count,comment,finish_reason,finish_user,end_time,platform_description,browser_name,os_info,area,country,province,city,creator,name,"-1" as idcard,"-1" as phone,itcast_school_id,itcast_school,itcast_subject_id,itcast_subject,"-1" as wechat,"-1" as qq,"-1" as email,gender,level,origin_type,information_way,working_years,technical_directions,customer_state,valid,anticipat_signup_date,clue_state,scrm_department_id,superior_url,superior_source,landing_url,landing_source,info_url,info_source,origin_channel,course_id,course_name,zhuge_session_id,is_repeat,tenant,activity_id,activity_name,follow_type,shunt_mode_id,shunt_employee_group_id, "9999-12-31" as ends_time , "2021-09-27" AS starts_time
FROM customer_clue where 1=1 and $CONDITIONS' \
--hcatalog-database itcast_ods \
--hcatalog-table customer_clue_temp \
-m 1-- 第三步: 通过 insert into + select 导入到目标表
insert into table itcast_ods.customer_clue partition(starts_time)
select * from itcast_ods.customer_clue_temp;
5.7 清洗转换操作
5.7.1 生成DWD层数据
作用: 清洗 和 转换 以及少量的维度退化
维度退化操作: 此层不需要做
清洗操作:
将标记删除的数据过滤掉转换操作:
1) 将create_date_time 转换为 yearinfo monthinfo dayinfo hourinfo
2) 将origin_type 转换为 origin_type_state (用于统计线上线下)
转换逻辑: origin_type的值为: NETSERVICE 或者 PRESIGNUP 认为线上 其余认为线下
3) 将clue_state 转换为 clue_state_stat (用于统计新老维度) -- 当前层无法转换的 (只能在DWM)
转换逻辑:clue_state的值为 VALID_NEW_CLUES 为新客户 其余暂定为老客户
4) 将校区和学科的 id字段, 如果为 0 或者 null 转换为 -1
编写SQL:
select id as rid,customer_id,create_date_time,if(itcast_school_id is null OR itcast_school_id = 0 , '-1',itcast_school_id) as itcast_school_id, deleted,origin_type,if(itcast_subject_id is not null, if(itcast_subject_id != 0,itcast_subject_id,'-1'),'-1') as itcast_subject_id, creator,substr(create_date_time,12,2) as hourinfo, if(origin_type in('NETSERVICE','PRESIGNUP'),'1','0') as origin_type_stat,substr(create_date_time,1,4) as yearinfo,substr(create_date_time,6,2) as monthinfo,substr(create_date_time,9,2) as dayinfo from itcast_ods.customer_relationship where deleted = 0 ;
将转换的SQL的结果保存到DWD层表中 (此操作, 并未执行, 而是执行后续的采样SQL)
insert into table itcast_dwd.itcast_intention_dwd partition(yearinfo,monthinfo,dayinfo)
select id as rid,customer_id,create_date_time,if(itcast_school_id is null OR itcast_school_id = 0 , '-1',itcast_school_id) as itcast_school_id, deleted,origin_type,if(itcast_subject_id is not null, if(itcast_subject_id != 0,itcast_subject_id,'-1'),'-1') as itcast_subject_id, creator,substr(create_date_time,12,2) as hourinfo, if(origin_type in('NETSERVICE','PRESIGNUP'),'1','0') as origin_type_stat,substr(create_date_time,1,4) as yearinfo,substr(create_date_time,6,2) as monthinfo,substr(create_date_time,9,2) as dayinfo from itcast_ods.customer_relationship where deleted = 0 ;
如果希望在灌入到DWD层的时候, 对数据进行采样操作: 比如只想要第5个桶
explain
insert into table itcast_dwd.itcast_intention_dwd partition(yearinfo,monthinfo,dayinfo)
select id as rid,customer_id,create_date_time,if(itcast_school_id is null OR itcast_school_id = 0 , '-1',itcast_school_id) as itcast_school_id, deleted,origin_type,if(itcast_subject_id is not null, if(itcast_subject_id != 0,itcast_subject_id,'-1'),'-1') as itcast_subject_id, creator,substr(create_date_time,12,2) as hourinfo, if(origin_type in('NETSERVICE','PRESIGNUP'),'1','0') as origin_type_stat,substr(create_date_time,1,4) as yearinfo,substr(create_date_time,6,2) as monthinfo,substr(create_date_time,9,2) as dayinfo from itcast_ods.customer_relationship tablesample(bucket 5 out of 10 on id) where deleted = 0 ;
执行采样导入到DWD层
--分区
SET hive.exec.dynamic.partition=true;
SET hive.exec.dynamic.partition.mode=nonstrict;
set hive.exec.max.dynamic.partitions.pernode=10000;
set hive.exec.max.dynamic.partitions=100000;
set hive.exec.max.created.files=150000;
--hive压缩
set hive.exec.compress.intermediate=true;
set hive.exec.compress.output=true;
--写入时压缩生效
set hive.exec.orc.compression.strategy=COMPRESSION;
--分桶
set hive.enforce.bucketing=true; -- 开启分桶支持, 默认就是true
set hive.enforce.sorting=true; -- 开启强制排序insert into table itcast_dwd.itcast_intention_dwd partition(yearinfo,monthinfo,dayinfo)
select id as rid,customer_id,create_date_time,if(itcast_school_id is null OR itcast_school_id = 0 , '-1',itcast_school_id) as itcast_school_id, deleted,origin_type,if(itcast_subject_id is not null, if(itcast_subject_id != 0,itcast_subject_id,'-1'),'-1') as itcast_subject_id, creator,substr(create_date_time,12,2) as hourinfo, if(origin_type in('NETSERVICE','PRESIGNUP'),'1','0') as origin_type_stat,substr(create_date_time,1,4) as yearinfo,substr(create_date_time,6,2) as monthinfo,substr(create_date_time,9,2) as dayinfo from itcast_ods.customer_relationship tablesample(bucket 5 out of 10 on id) where deleted = 0 ;
5.7.2 生成DWM层数据
由于DWM层的字段是来源于事实表和所有维度表中的字段, 此时如果生成DWM层数据, 必须要先将所有的表关联在一起
所有表的表与表之间的关联条件
客户意向表.creator = 员工表.id
员工表.tdepart_id = 部门表.id
线索表.customer_relationship_id = 客户意向表.id
客户意向表.itcast_school_id = 校区表.id
客户意向表.itcast_subject_id = 学科表.id
客户意向表.customer_id = 客户表.id
- SQL实现
select iid.customer_id,iid.create_date_time,c.area,iid.itcast_school_id,sch.name as itcast_school_name,iid.deleted,iid.origin_type,iid.itcast_subject_id,sub.name as itcast_subject_name,iid.hourinfo,iid.origin_type_stat,-- if(cc.clue_state = 'VALID_NEW_CLUES',1,if(cc.clue_state = 'VALID_PUBLIC_NEW_CLUE','0','-1')) as clue_state_stat, -- 此处有转换case cc.clue_state when 'VALID_NEW_CLUES' then '1'when 'VALID_PUBLIC_NEW_CLUE' then '0'else '-1' end as clue_state_stat,emp.tdepart_id,dept.name as tdepart_name,iid.yearinfo,iid.monthinfo,iid.dayinfo
from itcast_dwd.itcast_intention_dwd iidleft join itcast_ods.customer_clue cc on cc.customer_relationship_id = iid.ridleft join itcast_dimen.customer c on iid.customer_id = c.idleft join itcast_dimen.itcast_subject sub on iid.itcast_subject_id = sub.idleft join itcast_dimen.itcast_school sch on iid.itcast_school_id = sch.idleft join itcast_dimen.employee emp on iid.creator = emp.idleft join itcast_dimen.scrm_department dept on emp.tdepart_id = dept.id;
查看这条SQL语句, 相关的优化是否执行了呢?
开启优化:
--分区
SET hive.exec.dynamic.partition=true;
SET hive.exec.dynamic.partition.mode=nonstrict;
set hive.exec.max.dynamic.partitions.pernode=10000;
set hive.exec.max.dynamic.partitions=100000;
set hive.exec.max.created.files=150000;
--hive压缩
set hive.exec.compress.intermediate=true;
set hive.exec.compress.output=true;
--写入时压缩生效
set hive.exec.orc.compression.strategy=COMPRESSION;
--分桶
set hive.enforce.bucketing=true; -- 开启分桶支持, 默认就是true
set hive.enforce.sorting=true; -- 开启强制排序-- 优化:
set hive.auto.convert.join=true; -- map join
set hive.optimize.bucketmapjoin = true; -- 开启 bucket map join
-- 开启SMB map join
set hive.auto.convert.sortmerge.join=true;
set hive.auto.convert.sortmerge.join.noconditionaltask=true;
-- 写入数据强制排序
set hive.enforce.sorting=true;
set hive.optimize.bucketmapjoin.sortedmerge = true; -- 开启自动尝试SMB连接通过 执行计划, 查看是否生效: explain
除了这个SMB 优化生效后, 其他的表的都是存在有map join的方案
最后执行SQL, 查看是否可以正常执行:
说明:
通过执行发现, 开启优化, 执行速度, 异常的缓慢, 一分钟才可以执行 1%原因:
当前这种优化方案, 需要有非常的内存资源才可以运行, 如果没有, yarn会安排这些依次执行,导致执行效率更差
如果在生产环境中, 是完全可以开启的目前解决方案: 关闭掉所有的优化来执行
set hive.auto.convert.join=false;
set hive.optimize.bucketmapjoin = false; set hive.auto.convert.sortmerge.join=false;
set hive.auto.convert.sortmerge.join.noconditionaltask=false;set hive.enforce.sorting=false;set hive.optimize.bucketmapjoin.sortedmerge = false;
最终: 将查询出来的数据灌入到目标表即可
--分区
SET hive.exec.dynamic.partition=true;
SET hive.exec.dynamic.partition.mode=nonstrict;
set hive.exec.max.dynamic.partitions.pernode=10000;
set hive.exec.max.dynamic.partitions=100000;
set hive.exec.max.created.files=150000;
--hive压缩
set hive.exec.compress.intermediate=true;
set hive.exec.compress.output=true;
--写入时压缩生效
set hive.exec.orc.compression.strategy=COMPRESSION;
--分桶
set hive.enforce.bucketing=true; -- 开启分桶支持, 默认就是true
set hive.enforce.sorting=true; -- 开启强制排序-- 优化:
set hive.auto.convert.join=false; -- map join
set hive.optimize.bucketmapjoin = false; -- 开启 bucket map join
-- 开启SMB map join
set hive.auto.convert.sortmerge.join=false;
set hive.auto.convert.sortmerge.join.noconditionaltask=false;
-- 写入数据强制排序
set hive.enforce.sorting=false;
-- 开启自动尝试SMB连接
set hive.optimize.bucketmapjoin.sortedmerge = false; insert into table itcast_dwm.itcast_intention_dwm partition(yearinfo,monthinfo,dayinfo)
select iid.customer_id,iid.create_date_time,c.area,iid.itcast_school_id,sch.name as itcast_school_name,iid.deleted,iid.origin_type,iid.itcast_subject_id,sub.name as itcast_subject_name,iid.hourinfo,iid.origin_type_stat,-- if(cc.clue_state = 'VALID_NEW_CLUES',1,if(cc.clue_state = 'VALID_PUBLIC_NEW_CLUE','0','-1')) as clue_state_stat, -- 此处有转换case cc.clue_state when 'VALID_NEW_CLUES' then '1'when 'VALID_PUBLIC_NEW_CLUE' then '0'else '-1' end as clue_state_stat,emp.tdepart_id,dept.name as tdepart_name,iid.yearinfo,iid.monthinfo,iid.dayinfo
from itcast_dwd.itcast_intention_dwd iidleft join itcast_ods.customer_clue cc on cc.customer_relationship_id = iid.ridleft join itcast_dimen.customer c on iid.customer_id = c.idleft join itcast_dimen.itcast_subject sub on iid.itcast_subject_id = sub.idleft join itcast_dimen.itcast_school sch on iid.itcast_school_id = sch.idleft join itcast_dimen.employee emp on iid.creator = emp.idleft join itcast_dimen.scrm_department dept on emp.tdepart_id = dept.id;
5.8 统计分析操作
目的: 生产DWS层的数据, 数据来源于DWM
指标: 意向量
维度:
固有维度: 时间(年 月 日 小时), 线上线下, 新老维度
产品属性维度: 地区, 学科维度, 校区维度, 咨询中心维度, 来源渠道,总意向量
- 统计总意向量
-- 统计每年 线上线下 新老用户的总意向量
insert into table itcast_dws.itcast_intention_dws partition(yearinfo,monthinfo,dayinfo)
select count( distinct customer_id) as customer_total, '-1' as area,'-1' as itcast_school_id,'-1' as itcast_school_name,'-1' as origin_type,'-1' as itcast_subject_id,'-1' as itcast_subject_name,'-1' as hourinfo,origin_type_stat,clue_state_stat,'-1' as tdepart_id,'-1' as tdepart_name,yearinfo as time_str,'1' as grouptype,'5' as time_type,yearinfo,'-1' as monthinfo,'-1' as dayinfo
from itcast_dwm.itcast_intention_dwm
group by yearinfo,origin_type_stat,clue_state_stat;-- 统计每年每月 线上线下 新老用户的总意向量
insert into table itcast_dws.itcast_intention_dws partition(yearinfo,monthinfo,dayinfo)
select count( distinct customer_id) as customer_total, '-1' as area,'-1' as itcast_school_id,'-1' as itcast_school_name,'-1' as origin_type,'-1' as itcast_subject_id,'-1' as itcast_subject_name,'-1' as hourinfo,origin_type_stat,clue_state_stat,'-1' as tdepart_id,'-1' as tdepart_name,concat(yearinfo,'-',monthinfo) as time_str,'1' as grouptype,'4' as time_type,yearinfo,monthinfo,'-1' as dayinfo
from itcast_dwm.itcast_intention_dwm
group by yearinfo,monthinfo,origin_type_stat,clue_state_stat;
-- 统计每年每月每日 线上线下 新老用户的总意向量
insert into table itcast_dws.itcast_intention_dws partition(yearinfo,monthinfo,dayinfo)
select count( distinct customer_id) as customer_total, '-1' as area,'-1' as itcast_school_id,'-1' as itcast_school_name,'-1' as origin_type,'-1' as itcast_subject_id,'-1' as itcast_subject_name,'-1' as hourinfo,origin_type_stat,clue_state_stat,'-1' as tdepart_id,'-1' as tdepart_name,concat(yearinfo,'-',monthinfo,'-',dayinfo) as time_str,'1' as grouptype,'2' as time_type,yearinfo,monthinfo,dayinfo
from itcast_dwm.itcast_intention_dwm
group by yearinfo,monthinfo,dayinfo,origin_type_stat,clue_state_stat;
-- 统计每年每月每日每小时 线上线下 新老用户的总意向量
insert into table itcast_dws.itcast_intention_dws partition(yearinfo,monthinfo,dayinfo)
select count( distinct customer_id) as customer_total, '-1' as area,'-1' as itcast_school_id,'-1' as itcast_school_name,'-1' as origin_type,'-1' as itcast_subject_id,'-1' as itcast_subject_name,hourinfo,origin_type_stat,clue_state_stat,'-1' as tdepart_id,'-1' as tdepart_name,concat(yearinfo,'-',monthinfo,'-',dayinfo,' ',hourinfo) as time_str,'1' as grouptype,'1' as time_type,yearinfo,monthinfo,dayinfo
from itcast_dwm.itcast_intention_dwm
group by yearinfo,monthinfo,dayinfo,hourinfo,origin_type_stat,clue_state_stat;
- 统计 咨询中心维度
-- 统计每年线上线下, 新老用户产生各个咨询中心的意向量
insert into table itcast_dws.itcast_intention_dws partition(yearinfo,monthinfo,dayinfo)
select count( distinct customer_id) as customer_total, '-1' as area,'-1' as itcast_school_id,'-1' as itcast_school_name,'-1' as origin_type,'-1' as itcast_subject_id,'-1' as itcast_subject_name,'-1' as hourinfo,origin_type_stat,clue_state_stat,tdepart_id,tdepart_name,yearinfo as time_str,'5' as grouptype,'5' as time_type,yearinfo,'-1' as monthinfo,'-1' as dayinfo
from itcast_dwm.itcast_intention_dwm
group by yearinfo,origin_type_stat,clue_state_stat,tdepart_id,tdepart_name;
5.9 数据导出操作
指的: 从DWS层将数据导出到MYSQL中
- 第一步: 在mysql中创建目标表
CREATE TABLE IF NOT EXISTS scrm_bi.itcast_intention (`customer_total` INT COMMENT '聚合意向客户数',`area` varchar(100) COMMENT '区域信息',`itcast_school_id` varchar(100) COMMENT '校区id',`itcast_school_name` varchar(100) COMMENT '校区名称',`origin_type` varchar(100) COMMENT '来源渠道',`itcast_subject_id` varchar(100) COMMENT '学科id',`itcast_subject_name` varchar(100) COMMENT '学科名称',`hourinfo` varchar(100) COMMENT '小时信息',`origin_type_stat` varchar(100) COMMENT '数据来源:0.线下;1.线上',`clue_state_stat` varchar(100) COMMENT '客户属性:0.老客户;1.新客户',`tdepart_id` varchar(100) COMMENT '创建者部门id',`tdepart_name` varchar(100) COMMENT '咨询中心名称',`time_str` varchar(100) COMMENT '时间明细',`groupType` varchar(100) COMMENT '产品属性类别:1.总意向量;2.区域信息;3.校区、学科组合分组;4.来源渠道;5.咨询中心;',`time_type` varchar(100) COMMENT '时间维度:1、按小时聚合;2、按天聚合;3、按周聚合;4、按月聚合;5、按年聚合;',yearinfo varchar(100) COMMENT '年' ,monthinfo varchar(100) COMMENT '月',dayinfo varchar(100) COMMENT '日'
)
comment '客户意向dws表';
- 第二步:执行sqoop, 将数据全部到导出 MySQL中
sqoop export \
--connect "jdbc:mysql://192.168.52.150:3306/scrm_bi?useUnicode=true&characterEncoding=utf-8" \
--username root \
--password 123456 \
--table itcast_intention \
--hcatalog-database itcast_dws \
--hcatalog-table itcast_intention_dws \
-m 1
黑马在线教育数仓实战5相关推荐
- 黑马在线教育数仓实战2
1. 教育项目的数仓分层 回顾: 原有的基础分层 ODS层: 源数据层 作用: 对接数据源, 和数据源的数据保持相同的粒度(将数据源的数据完整的拷贝到ODS层中) 注意: ...
- 黑马在线教育数仓实战1
1. 教育项目的架构说明 项目的架构: 基于cloudera manager大数据统一管理平台, 在此平台之上构建大数据相关的软件(zookeeper,HDFS,YARN,HIVE,OOZI ...
- 黑马在线教育数仓实战3
3.4 访问咨询主题看板_建模操作 思考: 在创建表的时候, 需要考虑那些问题呢? 1) 表需要采用什么存储格式 2) 表需要采用什么压缩格式 3) 表需要构建什么类型表 3.4.1 数据存储格式 ...
- 黑马在线教育数仓实战7
1. hive的相关的优化 1.1 hive的相关的函数(补充说明) if函数: 作用: 用于进行逻辑判断操作 语法: if(条件, true返回信息,false返回信息) 注意: if函数支持嵌套使 ...
- 黑马在线教育数仓实战9
2.6 数据清洗转换操作 目的: 主要是用于从ODS以及DIM层 将数据灌入到DWM层操作 生成学生出勤状态信息表 涉及表: course_table_upload_detail: 日 ...
- 黑马在线教育数仓实战8
学生出勤主题看板 2.1 需求分析 回顾: 涉及维度, 指标, 涉及表, 字段, 以及需要清洗的内容, 需要转换的内容, 如果有多个表, 表与表关联条件 需求一: 统计指定时间段内,不同班级的出勤人数 ...
- 滴滴出行大数据数仓实战
我正在参加年度博客之星评选,请大家帮我投票打分,您的每一分都是对我的支持与鼓励. 2021年「博客之星」参赛博主:Maynor大数据 (感谢礼品.红包免费送!) https://bbs.csdn.ne ...
- 黑马在线教育项目---5、使用填充器创建数据库数据
黑马在线教育项目---5.使用填充器创建数据库数据 一.总结 一句话总结: ①创建填充器文件:#php artisan make:seeder ManagerTableSeeder ③执行填充器文件: ...
- 黑马在线教育项目---15-16、datatables插件
黑马在线教育项目---15-16.datatables插件 一.总结 一句话总结: datatables插件也比较好用,引入好插件的js和css后,核心代码也就是插件的初始化,如果要修改配置可以百度 ...
最新文章
- js笔记——call,apply,bind使用笔记
- 完美解决idea继承maven后,构建项目慢的问题
- 快速开发平台网格部件合并单元格。
- 我收集的鼠标指针样式-比较经典
- jQuery插件---ImageBox的使用
- Doctrine官方手册 - 缓存
- flutter对比Android绘制流程,Flutter与android的对比---View
- ggplot2箱式图两两比较_R绘图 第四篇:绘制箱图(ggplot2)
- “全国住房公积金”微信小程序正式上线 快速办理“异地转移”
- LeetCode 59. Spiral Matrix II
- IT公司组织机构和职位、职位职责
- DenseNet:比ResNet更优的CNN模型
- Android下载PDF文件
- ddr4 dqs 频率_你好,请问你知道DDR3中是DQS是什么意思吗
- linux mbr 转 gpt 数据丢吗,不丢失数据 MBR转GPT分区表教程
- html5获取坐标高德,vue 单纯的获取经纬度 百度与高德 H5
- 对面装修,办公室放置绿萝,袋装活性炭,空气净化器,有用吗?
- kubectl插件管理器krew
- Windows服务器搭建Node-Media-Server视频服务器
- 2023秋招360公司NLP算法岗面经