项目流程

step1: 需求分析(知道有哪些主题,哪些指标,哪些维度
step2: 建模分析(是否要压缩,行/列存储,索引,分区,分桶
step3: 建模操作,建库建表
step4: 数据采集(MySQL业务数据库 -> Hive(ODS层
step5: 数据清洗转换(空值过滤,空值转换,列值裁剪,切割
step6: 数据分析操作,结合主题,维度指标完成各种需求
step7: 数据导出操作,导出分析后的结果数据到mysql中,之后对接FineBI进行可视化展示

需求分析

提出需求

这一步就是根据需求把涉及到的表, 维度, 指标, 以及具体的维度字段, 维度字段提取出来

需求1- 总访问客户量

  • 统计指定时间段内,访问客户的总数量。能够下钻到小时数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
维度:
时间维度: 年 季度 月 天 小时

指标:
总访问客户量

涉及到表:
web_chat_ems_年_月 (事实表)

涉及到字段:
时间维度: create_time
特点: 一个字段中涵盖了多个字段的数据
转换操作: 需要将 create_time 转换为 yearinfo, quarterInfo, monthInfo, dayinfo,hourinfo
指标字段: sid、session_id、ip
注意: 先去重在count统计

需求2- 地区独立访客热力图

  • 统计指定时间段内,访问客户中各区域人数热力图。能够下钻到小时数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
涉及到维度:
时间维度: 年 季度 月 天 小时
区域维度

涉及到指标:
访问客户量

涉及到表:
web_chat_ems_年_月 (事实表)

涉及到字段:
时间维度字段: create_time
转换操作: 需要将 create_time 转换为 yearinfo, quarterInfo, monthInfo, dayinfo,hourinfo
区域维度: area, country, province,city
指标字段: sid、session_id、ip
先去重, 后统计

需求3- 访客咨询率趋势

  • 统计指定时间段内,不同地区(省、市)访问的客户中发起咨询的人数占比;
  • 咨询率=发起咨询的人数/访问客户量;客户与网咨有说一句话的称为有效咨询。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
涉及到维度:
时间维度: 年 季度 月 天
地区维度: 省、市、区域

涉及到指标:
咨询客户量, 访问客户量

细点:
当遇到需要计算比率的相关的指标的时候, 我们前期只需要计算其分子和分母即可, 最后比率在APP层计算即可


涉及表:
web_chat_ems_年_月 (事实表)


涉及到字段:
时间维度: create_time
转换操作: 需要将 create_time 转换为 yearinfo, quarterInfo, monthInfo, dayinfo,hourinfo

地区维度: area,province,city

指标维度:
访问客户量: sid、session_id、ip
去重统计
咨询客户量: sid、session_id、ip
去重统计
判断依据: 必须保证 msg_count >= 1

发现:
访问量在上述的SQL中, 统计的更加细化, 已经涵盖了当前这个需求内容, 所以此处的访问量无需在计算了
此处只需要算咨询量:
在计算咨询量的时候, 既然访问量算的更加细化了, 建议咨询量也以此为标准, 后续可以应用更多需求

需求4- 客户访问量和访客咨询率双轴趋势

  • 统计指定时间段内,每日客户访问量/咨询率双轴趋势图。能够下钻到小时数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
涉及维度: 
时间维度: 年 季度 月 天 小时

涉及指标:
访问量: 不需要计算了, 直接复用需求一的内容
咨询量:

涉及表:
web_chat_ems_年_月 (事实表)

涉及字段:
时间维度: create_time
转换操作: 需要将 create_time 转换为 yearinfo, quarterInfo, monthInfo, dayinfo,hourinfo

咨询量指标: sid、session_id、ip
去重统计, 统计的时候, 需要进行判断: 必须保证 msg_count >= 1

需求5- 时间段访问客户量趋势 (不需要关心了, 前序涵盖)

  • 统计指定时间段内,1-24h之间,每个时间段的访问客户量。

    横轴:1-24h,间隔为一小时,纵轴:指定时间段内同一小时内的总访问客户量。

需求6- 来源渠道访问量占比

  • 统计指定时间段内,不同来源渠道的访问客户量占比。能够下钻到小时数据。
    • 占比: 总访问量与各来源渠道的占比情况
    • 占比: 各来源渠道中,访问量的占比 (依次为标准)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
涉及维度: 
时间维度: 年 季度 月 天 小时
来源渠道
涉及指标:
访问客户量
咨询客户量

涉及表:
web_chat_ems_年_月 (事实表)

涉及字段:
时间维度: create_time
来源渠道: origin_channel
访问量和咨询量指标字段: sid、session_id、ip
访问量和咨询量区别:
咨询量多个一个判断: msg_count >= 1

需求7- 搜索来源访问量占比

  • 统计指定时间段内,不同搜索来源的访问客户量占比。能够下钻到小时数据。
    • 占比: 总访问量与各搜索来源的占比情况 (依次为标准)
    • 占比: 各搜索来源中,访问量的占比
1
2
3
4
5
6
7
8
9
10
11
12
13
涉及维度:
时间维度: 年 季度 月 天 小时
搜索来源
涉及指标:
访问量

涉及表:
web_chat_ems_年_月 (事实表)

涉及字段:
时间字段: create_time
搜索来源: seo_source
指标字段: sid、session_id、ip

需求8- 活跃页面排行榜

  • 统计指定时间段内,产生访问客户量最多的页面排行榜TOPN。能够下钻到小时数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
涉及维度:
时间维度: 年 季度 月 天 小时
受访页面

涉及到指标:
访问客户量

涉及表:
web_chat_text_ems_年_月 (事实表)
web_chat_ems(事实表)
涉及字段:
时间维度: create_time
受访页面维度: from_url
指标字段: sid、session_id、ip

表关联条件:
id = id


说明:
当发现有些字段无法确定的时候, 此时需要通过查看表的数据结构, 从当中找相关的字段, 如果找不到, 思考怎么获得这个字段
以当前这个为例, 发现 web_chat_text_ems 和 web_chat_ems 是一种一对一的关系, 简单说, 本质就是一个表, 所以可以直接使用 web_chat_ems中相关的维度字段来处理


维度退化操作: 降维度
将两个表合并为一个表

需求汇总

将上述需求设计到的表和字段进行汇总.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
访问客户量: 共计有 25个需求
涉及到维度:
常驻维度: 每一个需求都需要计算的维度
时间维度: 年 季度 月 天 小时
产品属性维度: 有这个维度, 但是并不是每个需求都有的
地区维度
来源渠道维度
搜索来源维度
受访页面
总访问量
咨询客户量: 共计有 15个需求
涉及维度:
常驻维度:
时间维度: 年 季度 月 天 小时
产品属性维度:
地区维度
来源渠道
总咨询量


涉及表:
web_chat_text_ems_年_月 (事实表) wcte
web_chat_ems(事实表) wce


涉及字段:
时间维度: wce.create_time
地区维度: wce.area , wce.country, wce.province,wce.city
来源渠道维度: wce.origin_channel
搜索来源维度: wce.seo_source
受访页面: wcte.from_url
指标字段:
sid、ip、session_id

两个表关联条件:
wcte.id = wce.id

需要转换内容:
时间维度需要转换: 需要将create_time 转换为 年 季度 月 天 小时 (拉宽操作)

合并降维操作: 将两个表合并为一个表

是否需要进行拉链呢? 数据只有新增操作, 所以不需要进行拉链操作
同步方式: 仅新增同步

建模分析

建模分析主要的作用: 用于分析当前这个主题需要进行那些分层操作, 每个层次结构中需要有那些表, 每个表中需要有那些字段

ODS层: 数据源层(贴源层)

1
2
3
4
5
6
7
8
9
10
作用: 对接数据源, 保留最完整的原始数据。用于将数据源中数据完整的拷贝到ODS层, 一般来说数据源中有哪些表, 那么会在ODS层构建有那些表, 与之一一对应
字段和原始数据一致,需要加一个分区字段:抽取数据的日期

建表:
需要构建两张表: web_chat_ems 和 web_chat_text_ems
每个表的字段有那些: 字段内容与业务库的字段一致 + 分区字段(dt)
是否需要分区操作: 仅新增同步需要构建的, 同步周期为 天
是否需要分桶操作: 不需要, 这样采集数据更加方便
选择什么存储格式: ORC, SNAPPY
选择什么压缩格式: SNAPPY

DWD层: 明细层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
作用: 提供高质量的数据
1- 清洗操作
2- 转换操作
3- 拉链实现
说明:
DWD层的表的数量与ODS层表的数量是一致的, 表的字段基本上都是涵盖(除非这些字段以后完全用不上)

表字段不受清洗操作的影响,因为清洗操作只过滤行数据,不影响字段列;
受到转换操作的影响,转换出来的新字段,需要加到DWD表中。


当前主题, 没有拉链操作, 有清洗和转换操作, 需要将其中一个表中create_time字段转换为 年 季度 月 天 小时

建表:
需要构建 web_chat_ems_dwd和 web_chat_text_ems表
表字段:
将所有原有字段全部保留 + 扩展出来新字段 + 分区字段(dt)
是否需要分区表: 需要的, dt 天分区
是否需要分桶表: 建分桶表(走SMB优化)
建表:
1- 两个表必须都是分桶表
2- 分桶字段必须是JOIN字段,同时还需要进行排序
3- 桶的数量必须一致
选择什么存储格式: ORC
选择什么压缩格式: SNAPPY
思考: 还可以走什么优化手段

DWB层: 中间层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
作用:
进行维度退化操作, 形成宽表操作(多表合并, 进行Join)

建表:
需要构建为一张表: web_chat_ems_dwb
此表需要将DWD层两个表合并在一起, 合并后, 所有字段都要全部保留
是否需要分区表: 需要的, dt 天分区
是否需要分桶表: 1- 是否需要采样(1)指标统计是否是相对指标 2) 数据量是否很庞大, 测试环境无法运行, 此时需要采样) 2- 是否需要提升查询效率(不需要了)
不需要构建分桶表
选择什么存储格式: ORC
选择什么压缩格式: SNAPPY

思考: 还可以走什么优化手段:
目前在计算咨询量的时候, 需要 msg_count >=1 此时可以尝试使用索引优化(row group index 索引要求, bloom filter index)
满足了 row group index 索引要求

DWS层: 提前聚合(业务层)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
作用: 
提前聚合操作

注意:当涉及到去重操作时,不要提前聚合。

比如说:
按照 年 月 日 统计, 此时可以在DWS层先按照日进行统计, 后续在日统计结果基础上, 统计 月 和 年


当下主题的指标统计: 先去重, 然后才能统计 一般不能进行提前聚合, 因为一旦聚合后, 导致上卷统计结果不准确

注意:
当下主题, 无法进行提前聚合操作, 所以 当前主题不需要有DWS层

举个例子:
2022年 3月 1号 访问量100条, 其中重复的有 30个

2022年 3月 2号 访问量 100条, 其中重复的50个

注意: 同一个用户有可能在 1号 和 2号都访问了

先按照天统计:
3月1号访问量为 70个
3月2号访问量为 50个

统计3月份访问量:
70 + 50 = 120个

实际上, 如果直接对原有数据统计, 共计只有100个, 其中有20 个 1号和2号都来了

DM层:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
作用: 
细化统计分析操作. 基于DWS层结果, 进行上卷统计处理

指标字段 + 维度字段 + 两个经验字段

访问量: 共计有 25个需求
涉及到维度:
固有维度: 每一个需求都需要计算的维度
时间维度: 年 季度 月 天 小时
产品属性维度: 有这个维度, 但是并不是每个需求都有的
地区维度
来源渠道维度
搜索来源维度
受访页面
总访问量

咨询量: 共计有 15个需求
涉及维度:
固有维度:
时间维度: 年 季度 月 天 小时

产品属性维度:
地区维度:
来源渠道
总咨询量



visit_consult_dm表需要有那些字段呢?
指标字段 + 维度字段 + 两个经验字段
visit_sid, visit_session_id, visit_ip, consult_sid, consult_session_id, consult_ip,
yearinfo,quarterinfo,monthinfo,dayinfo,hourinfo,area,origin_channel,seo_source,from_url,
time_type,group_type


表是否需要构建分区表: 需要的 分区字段就是我们的时间字段
可以将 yearinfo,quarterinfo,monthinfo,dayinfo 作为分区字段

表是否为分桶表: 不需要了
选择什么存储格式: ORC
选择什么压缩格式: SNAPPY

思考可以走什么优化?
可以考虑有可能出现group by的数据倾斜问题, 如何解决

RPT层(ADS,APP层) : 数据应用层

1
2
3
4
作用: 
对接外部应用, 应用方需要什么数据, 从DM层提取出来, 放置到DM层中

对接最终应用: 此层就根据实际需求, 建表存储即可

建模操作

根据上面分析到的数据建库建表.

ODS层表:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
-- 1- 创建库
drop database if exists edu_ods;
create database if not exists edu_ods;

-- 2- 创建表:
create table if not exists edu_ods.web_chat_ems(

id INT comment '主键' ,
create_date_time STRING comment '数据创建时间' ,
session_id STRING comment '七陌SESsionId' ,
sid STRING comment '访客id' ,
create_time STRING comment '会话创建时间' ,
seo_source STRING comment '搜索来源' ,
seo_keywords STRING comment '关键字' ,
ip STRING comment 'IP地址' ,
AREA STRING comment '地域' ,
country STRING comment '所在国家' ,
province STRING comment '省' ,
city STRING comment '城市' ,
origin_channel STRING comment '投放渠道' ,
`user` STRING comment '所属坐席' ,
manual_time STRING comment '人工开始时间' ,
begin_time STRING comment '坐席领取时间' ,
end_time STRING comment '会话结束时间' ,
last_customer_msg_time_stamp STRING comment '客户最后一条消息的时间',
last_agent_msg_time_stamp STRING comment '坐席最后一下回复的时间',
reply_msg_count INT comment '客服回复消息数' ,
msg_count INT comment '客户发送消息数' ,
browser_name STRING comment '浏览器名称' ,
os_info STRING comment '系统名称'
)
partitioned by(dt string)
row format delimited fields terminated by '\t'
stored as orc
TBLPROPERTIES('orc.compress'='SNAPPY' );


create table if not exists edu_ods.web_chat_text_ems(
id INT comment'主键',
referrer string comment'上级来源页面',
from_url string comment'会话来源页面',
landing_page_url string comment'访客着陆页面',
url_title string comment'咨询页面title',
platform_description string comment'客户平台信息',
other_params string comment'扩展字段中数据',
history string comment'历史访问记录'
)
partitioned by(dt string)
row format delimited fields terminated by '\t'
stored as orc
TBLPROPERTIES('orc.compress'='SNAPPY' );

DWD层建表操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
-- 1- 创建库
drop database if exists edu_dwd;
create database if not exists edu_dwd;

-- 2) 创建表
drop table if exists edu_dwd.web_chat_ems_dwd;
create table if not exists edu_dwd.web_chat_ems_dwd(

id INT comment '主键' ,
create_date_time STRING comment '数据创建时间' ,
session_id STRING comment '七陌SESsionId' ,
sid STRING comment '访客id' ,
create_time STRING comment '会话创建时间' ,
seo_source STRING comment '搜索来源' ,
seo_keywords STRING comment '关键字' ,
ip STRING comment 'IP地址' ,
AREA STRING comment '地域' ,
country STRING comment '所在国家' ,
province STRING comment '省' ,
city STRING comment '城市' ,
origin_channel STRING comment '投放渠道' ,
`user` STRING comment '所属坐席' ,
manual_time STRING comment '人工开始时间' ,
begin_time STRING comment '坐席领取时间' ,
end_time STRING comment '会话结束时间' ,
last_customer_msg_time_stamp STRING comment '客户最后一条消息的时间',
last_agent_msg_time_stamp STRING comment '坐席最后一下回复的时间',
reply_msg_count INT comment '客服回复消息数' ,
msg_count INT comment '客户发送消息数' ,
browser_name STRING comment '浏览器名称' ,
os_info STRING comment '系统名称' ,
hourinfo string comment '小时'
)
partitioned by(yearinfo string,quarterinfo string,monthinfo string,dayinfo string)
clustered by(id) sorted by (id asc) into 10 buckets
row format delimited fields terminated by '\t'
stored as orc
TBLPROPERTIES(
'orc.compress'='SNAPPY' ,
"orc.bloom.filter.columns"="id"
);

drop table if exists edu_dwd.web_chat_text_ems_dwd;
create table if not exists edu_dwd.web_chat_text_ems_dwd(
id INT comment'主键',
referrer string comment'上级来源页面',
from_url string comment'会话来源页面',
landing_page_url string comment'访客着陆页面',
url_title string comment'咨询页面title',
platform_description string comment'客户平台信息',
other_params string comment'扩展字段中数据',
history string comment'历史访问记录'
)
partitioned by(dt string)
clustered by(id) sorted by (id asc) into 10 buckets
row format delimited fields terminated by '\t'
stored as orc
TBLPROPERTIES(
'orc.compress'='SNAPPY',
"orc.bloom.filter.columns"="id"
);

DWB层:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
-- 创建库
drop database if exists edu_dwb;
create database if not exists edu_dwb;

-- 建表:
create table if not exists edu_dwb.web_chat_ems_dwb(
id INT comment '主键' ,
create_date_time STRING comment '数据创建时间' ,
session_id STRING comment '七陌SESsionId' ,
sid STRING comment '访客id' ,
create_time STRING comment '会话创建时间' ,
seo_source STRING comment '搜索来源' ,
seo_keywords STRING comment '关键字' ,
ip STRING comment 'IP地址' ,
AREA STRING comment '地域' ,
country STRING comment '所在国家' ,
province STRING comment '省' ,
city STRING comment '城市' ,
origin_channel STRING comment '投放渠道' ,
`user` STRING comment '所属坐席' ,
manual_time STRING comment '人工开始时间' ,
begin_time STRING comment '坐席领取时间' ,
end_time STRING comment '会话结束时间' ,
last_customer_msg_time_stamp STRING comment '客户最后一条消息的时间',
last_agent_msg_time_stamp STRING comment '坐席最后一下回复的时间',
reply_msg_count INT comment '客服回复消息数' ,
msg_count INT comment '客户发送消息数' ,
browser_name STRING comment '浏览器名称' ,
os_info STRING comment '系统名称' ,
hourinfo string comment '小时',
referrer string comment'上级来源页面',
from_url string comment'会话来源页面',
landing_page_url string comment'访客着陆页面',
url_title string comment'咨询页面title',
platform_description string comment'客户平台信息',
other_params string comment'扩展字段中数据',
history string comment'历史访问记录'

)
partitioned by(yearinfo string,quarterinfo string,monthinfo string,dayinfo string)
row format delimited fields terminated by '\t'
stored as orc
TBLPROPERTIES(
'orc.compress'='SNAPPY' ,
'orc.create.index'='true'
);

DM层:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
-- 1- 创建库
drop database if exists edu_dm;
create database if not exists edu_dm;

create table if not exists edu_dm.visit_consult_dm(
visit_sid bigint comment 'sid访问量',
visit_session_id bigint comment 'session_id访问量',
visit_ip bigint comment 'ip访问量',
consult_sid bigint comment 'sid咨询量',
consult_session_id bigint comment 'session_id咨询量',
consult_ip bigint comment 'ip咨询量',
hourinfo string comment '小时',
area string comment '地区维度',
origin_channel string comment '来源渠道维度',
seo_source string comment '搜索来源维度',
from_url string comment '受访url',
time_type string comment '时间标记: 1 小时 2 天 3月 4 季度 5 年',
group_type string comment '产品属性维度标记: 1 地区 2 来源渠道 3 搜索来源 4 受访url 5总访问量'
)
partitioned by(yearinfo string,quarterinfo string,monthinfo string,dayinfo string)
row format delimited fields terminated by '\t'
stored as orc
TBLPROPERTIES(
'orc.compress'='SNAPPY'
);

RPT建表:

1
暂时不构建, 后续根据应用方需要, 动态建表即可

数据采集

Sqoop命令,个人感觉都写麻了.

数据清洗转换

数据分析操作

数据导出操作