商业智能系统,通常简称为商业智能系统,是商业智能软件的简称,是为提高企业经营绩效而采用的一系列方法、技术和软件的总和。通常被理解为将企业中的现有数据转换为知识并帮助企业做出明智的业务决策的工具。
BI系统中的数据来自企业的其他业务系统。例如,一个面向业务的企业,其业务智能系统数据包括业务系统订单、库存、交易账户、客户和供应商信息,以及企业所属行业和竞争对手的数据,以及其他外部环境数据。这些数据可能来自于CRM、SCM和发票等业务系统。
商业BI系统的组成部分:
受互联网+概念的催化,教育市场发展火热,越来越多的教育机构和平台不断涌现,包括有线上学习和线下培训,K12教育和职业教育等,那些注重用户服务、教育质量的平台会最终胜出。目前的企业痛点:
如何提高用户服务水平,提高教育质量是每个机构都面临的问题。信息的共享和利用不充分,就导致尽管学校多年的信息化应用积累了大量的数据,但信息孤岛的壁垒一直没有打破,对这些数据无法进一步的挖掘、分析、加工、整理,不能给学校教育、教学、研发、总务等各方面管理决策提供科学、有效的数据支撑。
大数据技术的应用可以从海量的用户行为数据中进行挖掘分析,根据分析结果优化平台的服务质量,最终满足用户的需求。
教育大数据分析平台项目就是将大数据技术应用于教育培训领域,为企业经营提供数据支撑:
目的: 分析每一个调研需求需要计算什么指标, 以及计算这个指标需要通过那些维度,而且还包括计算这个需求涉及到哪些表和哪些字段。
客户访问和咨询主题,顾名思义,分析的数据主要是客户的访问数据和咨询数据。但是经过需求调研,这里的访问数据,实际指的是访问的客户量,而不是客户访问量。原始数据来源于咨询系统的mysql业务数据库。
用户关注的核心指标有:
说明:统计指定时间段内,访问客户中各区域人数热力图。能够下钻到小时数据。
展现:地图热力图
指标:按照地区聚合访问的客户数量
维度:年、季度、月
粒度:天
条件:年、季度、月
数据来源:咨询系统的web_chat_ems_2019_12等月表
按年:显示指定年范围内每天的客户访问量
按季度:显示指定季度范围内每天的客户访问量
按月:显示指定月份范围内每天的客户访问量
指标: 访问量
维度:
时间维度: 年 季度 月 天 小时
涉及到哪些表: web_chat_ems_2019_12
涉及到哪些字段:
时间维度: create_time
说明: 发现create_time字段中包含有年 月 天 小时这些数据, 此时可以认为一个字段中涵盖了多个字段的数据
处理方式: 后期需要对此字段进行转换处理工作
将create_time 转换为: yearinfo monthinfo dayinfo hourinfo ....
指标字段: sid
说明: 指标计算的逻辑 先对sid进行去重操作, 然后统计个数过程
说明:统计指定时间段内,访问客户中各区域人数热力图。能够下钻到小时数据。
展现:地图热力图
指标:按照地区聚合访问的客户数量
维度:年、季度、月
粒度:天
条件:年、季度、月
数据来源:咨询系统的web_chat_ems_2019_12等月表
按年:显示指定年范围内每天的客户访问量
按季度:显示指定季度范围内每天的客户访问量
按月:显示指定月份范围内每天的客户访问量
指标: 访问量
维度:
时间维度: 年 季度 月 天 小时
区域维度:
涉及到哪些表: web_chat_ems_2019_12
涉及到哪些字段:
时间维度: create_time
区域维度: area
指标字段: sid
说明:统计指定时间段内,不同地区(省、市)访问的客户中发起咨询的人数占比;
咨询率=发起咨询的人数/访问客户量;客户与网咨有说一句话的称为有效咨询。
展现:线状图
指标:访客咨询率
维度:年、月、城市
粒度:天
条件:年、季度、月、省、市
数据来源:咨询系统的web_chat_ems_2019_12等月表
按年:显示指定年范围内每天的客户访问量
按季度:显示指定季度范围内每天的客户访问量
按月:显示指定月份范围内每天的客户访问量
占比计算: 统计出每个地区的总访问量 和 每个地区发起咨询的人数之间比例
指标: 访问量 和 咨询量
维度:
时间维度: 年 季度 月 天 小时
区域维度
说明: 访问量的统计可以直接复用需求2的结果即可, 此处可以省略
涉及到哪些表: web_chat_ems_2019_12
涉及到哪些字段:
时间维度: create_time
区域维度: area
咨询量判断: msg_count >= 1 即可
指标字段: sid
咨询量指标计算:
先对数据进行过滤得出咨询数据, 然后通过先去重 在求个数过程
说明:统计指定时间段内,每日客户访问量/咨询率双轴趋势图。能够下钻到小时数据。
每日客户访问量可以复用指标2数据;
咨询率可以复用指标3的数据。
按年:显示指定年范围内每天的客户访问量
按季度:显示指定季度范围内每天的客户访问量
按月:显示指定月份范围内每天的客户访问量
指标: 访问量 和 咨询量
维度:
时间维度: 年 季度 月 天 小时
说明: 访问量的统计可以直接复用需求1的结果即可
涉及到哪些字段:
时间维度: create_time
说明: 发现create_time字段中包含有年 月 天 小时这些数据, 此时可以认为一个字段中涵盖了多个字段的数据
处理方式: 后期需要对此字段进行转换处理工作
将create_time 转换为: yearinfo monthinfo dayinfo hourinfo ....
指标字段: sid
说明: 指标计算的逻辑 先对sid进行去重操作, 然后统计个数过程
添加一个咨询数据过滤的条件:
msg_count >= 1 即可
说明:统计指定时间段内,1-24h之间,每个时间段的访问客户量。
横轴:1-24h,间隔为一小时,纵轴:指定时间段内同一小时内的总访问客户量。
展现:线状图、柱状图、饼状图
指标:某小时的总访问客户量
维度:天
粒度:区间内小时段
条件:天
数据来源:咨询系统的web_chat_ems_2019_12等月表
指标: 访问量
维度:
时间维度 : ....
此需求的结果 在需求1中 已经涵盖了, 不需要再次分析
说明:统计指定时间段内,不同来源渠道的访问客户量占比。能够下钻到小时数据。
展现:饼状图
指标:比值
维度:年、季度、月
粒度:天
条件:年、季度、月
数据来源:咨询系统的web_chat_ems_2019_12等月表
按年:显示指定年范围内每天的客户访问量
按季度:显示指定季度范围内每天的客户访问量
按月:显示指定月份范围内每天的客户访问量
指标: 访问量 和 咨询量
维度:
时间维度: 年 季度 月 天 小时
来源渠道维度
涉及到哪些表: web_chat_ems_2019_12
涉及到哪些字段:
时间维度: create_time
来源渠道维度: origin_channel
指标字段: sid
说明:统计指定时间段内,不同搜索来源的访问客户量占比。能够下钻到小时数据。
展现:饼状图
指标:比值
维度:年、季度、月
粒度:天
条件:年、季度、月
数据来源:咨询系统的web_chat_ems_2019_12等月表
按年:显示指定年范围内每天的客户访问量
按季度:显示指定季度范围内每天的客户访问量
按月:显示指定月份范围内每天的客户访问量
指标: 访问量
维度:
时间维度 : 年 季度 月 天 小时
搜索来源渠道维度
涉及到哪些表: web_chat_ems_2019_12
涉及到那些字段:
时间维度: create_time
搜索来源维度字段: seo_source
指标字段: sid
说明:统计指定时间段内,产生访问客户量最多的页面排行榜TOPN。能够下钻到小时数据。
展现:柱状图
指标:访问客户量
维度:页面、年、季度、月
粒度:天
条件:年、季度、月、Top数量
数据来源:咨询系统的 web_chat_text_ems_2019_11等月表
按年:显示指定年范围内每天的客户访问量
按季度:显示指定季度范围内每天的客户访问量
按月:显示指定月份范围内每天的客户访问量
指标: 访问量
维度:
时间维度: 年 季度 月 天 小时
受访页面维度:
涉及到哪些表: web_chat_text_ems_2019_12
涉及到哪些字段:
时间维度: 暂不知道
受访页面维度: from_url
指标计算: 直接计算总数量
总结:
指标: 访问量
维度:
固有维度:
时间维度: 年 季度 月 天 小时
产品属性维度:
总访问量
地区维度
来源渠道维度
搜索来源维度
受访页面维度
-------------------------------------
指标: 咨询量
维度:
固有维度:
时间维度: 年 季度 月 天 小时
产品属性维度:
总咨询量
地区维度
来源渠道维度
发现点: 不管计算咨询量还是访问量 都使用的同一个表, 至少咨询量比访问量在计算的时候多个一个条件:
msg_count >=1
涉及到表: web_chat_ems_2019_12 和 web_chat_text_ems_2019_12
涉及到字段:
web_chat_ems_2019_12:
指标: sid (咨询量 和 访问量)
说明: 先去重, 在统计个数过程
时间维度: create_time
地区维度: area
来源渠道维度: origin_channel
搜索来源维度: seo_source
web_chat_text_ems_2019_12:
受访页面维度: from_url
需求转换的点:
create_time字段 后期需要进行转换操作
访问客户量的数据来源于咨询系统的访问会话月表web_chat_ems,表名的格式为web_chat_ems_年_月,年份为4位数字,月份为二位数字,如果为单数时,前面会用0来补全,比如web_chat_ems_2019_07。
web_chat_text_ems表是访问附属月表,表名的格式和web_chat_ems相同。web_chat_ems和web_chat_text_ems是一一对应的,通过主键id进行关联。
1、新建数据库:在业务库中, 构建 业务数据库: (MySQL) 请采用课件提供建库语句, 以免出现中文乱码问题
create database nev default character set utf8mb4 collate utf8mb4_unicode_ci;
2、执行相关的SQL的脚本, 将数据导入到nev数据库中
web_chat_ems表结构
create table web_chat_ems_2019_07
(
id int auto_increment comment '主键' primary key,
create_date_time timestamp null comment '数据创建时间',
session_id varchar(48) default '' not null comment '会话系统sessionId',
sid varchar(48) collate utf8_bin default '' not null comment '访客id',
create_time datetime null comment '会话创建时间',
seo_source varchar(255) collate utf8_bin default '' null comment '搜索来源',
seo_keywords varchar(512) collate utf8_bin default '' null comment '关键字',
ip varchar(48) collate utf8_bin default '' null comment 'IP地址',
area varchar(255) collate utf8_bin default '' null comment '地域',
country varchar(16) collate utf8_bin default '' null comment '所在国家',
province varchar(16) collate utf8_bin default '' null comment '省',
city varchar(255) collate utf8_bin default '' null comment '城市',
origin_channel varchar(32) collate utf8_bin default '' null comment '来源渠道(广告)',
user varchar(255) collate utf8_bin default '' null comment '所属坐席',
manual_time datetime null comment '人工开始时间',
begin_time datetime null comment '坐席领取时间 ',
end_time datetime null comment '会话结束时间',
last_customer_msg_time_stamp datetime null comment '客户最后一条消息的时间',
last_agent_msg_time_stamp datetime null comment '坐席最后一下回复的时间',
reply_msg_count int(12) default 0 null comment '客服回复消息数',
msg_count int(12) default 0 null comment '客户发送消息数',
browser_name varchar(255) collate utf8_bin default '' null comment '浏览器名称',
os_info varchar(255) collate utf8_bin default '' null comment '系统名称'
);
web_chat_text_ems表结构:
create table web_chat_text_ems_2019_07
(
id int not null comment '主键' primary key,
referrer text collate utf8_bin null comment '上级来源页面',
from_url text collate utf8_bin null comment '会话来源页面',
landing_page_url text collate utf8_bin null comment '访客着陆页面',
url_title text collate utf8_bin null comment '咨询页面title',
platform_description text collate utf8_bin null comment '客户平台信息',
other_params text collate utf8_bin null comment '扩展字段中数据',
history text collate utf8_bin null comment '历史访问记录'
);
根据主题的需求,我们可以看出,包含的指标有一些是可以提取合并的:
由此我们可以推断出,指标有两个:访问客户量和咨询客户量。
虽然访问客户量的时间维度只有年、季度、月,但是展示粒度要具体到天,所以统计时也要包含日维度。同时要求能够下钻到小时数据,所以维度中也要包含小时。
来源渠道访客量占比,虽然最终要的是占比的比值,但是这个比值是可以通过具体的访客量计算出来,所以我们只需要提供不同来源渠道的访客量数据,柱状图前端就能够自动的计算比值。因此这里的指标也归类于访问客户量,维度为来源渠道。
活跃页面排行榜,字面看是和页面相关的指标,实际统计的却是每个页面的访问客户量,然后再进行排序后得出的排行榜。所以这里的指标也归类于访问客户量,统计的维度是具体的页面。但是要注意这里的数据来源有变化。
维度包括:年、季度、月、天、小时(天区间内小时段)、地区、来源渠道、搜索来源、会话来源页面、总访问量。
访客咨询率趋势统计中,访客咨询率=发起咨询的人数/访问客户量,分母访问客户量我们可以复制上面的指标数据,而分子咨询客户量则是我们要统计的新指标。
维度包括:年、季度、月、日、地区、来源渠道。
抽取咨询原始数据到ODS层以后,如何分析出对应维度的数据呢?
我们可以采取结果导向的方式来进行倒推:
目的: 要计算此主题, 需要如何构建数仓分层, 每一层需要有那些表, 表中有那些字段
ODS层: 源数据层
1) 在ODS层, 可以放置两张表(在业务端有二张跟此主题相关的事实表)
web_chat_ems 和 web_chat_text_ems
2) ODS层的两个表中字段 和 业务库中对应表的字段保持一致(业务库中表有几个字段, 此ODS层表中也应该有几个字段)
注意:
在后期执行操作的时候, 先进行全量分析过程, 然后后期都是增量分析,此时需要从ODS层拿到增量数据, 如何区分增量数据呢?
核心点: 通过时间
所以:
在ODS层建表的时候, 比业务库的表多一个字段,此字段主要作用用于标识抽取时间: start_time
DW层: 数据仓库层
DWD层: 明细层
清洗什么内容? 没有清洗的工作 , 因为数据来源于mysql, 数据结构是完整, 同时所有数据都是需要的, 所以也不需要处理
转换什么内容?
1. create_time : (需求必须要转换)
原始数据: 2019-07-02 00:00:00
发现: 一个字段里面糅杂了太多字段数据, 需要对其进行转换
转换为:
yearinfo quarterInfo monthinfo dayinfo hourinfo
2. 将create_time转换为时间戳的操作(为了讲解时间函数)
,create_time,
hourinfo,yearinfo, quarterInfo, monthinfo, dayinfo
注意: 以上字段, 是需要进行清洗和转换后, 保留的字段
此时DWD层表: 将上述的字段 和 ODS层中事实表所有的字段汇总在一起, 构建成DWD层表
实际在生产中,具体操作:
1) 第一种, 如果事实表中字段比较多, 一般做法 可以只将需要的字段抽取出来即可
2) 第二种, 如果表中字段比较少, 一般做法, 全部都获取出来
最终形成的表字段:
sid,session_id,ip ,create_time,area,origin_channel,seo_source,referrer,from_url,
landing_page_url,url_title,platform_description,other_params,history,msg_count
hourinfo,yearinfo, quarterInfo, monthinfo, dayinfo
DWM层: 中间层
1) 维度退化操作: 此功能在此主题中不存在, 因为没有维度表
2) 做提前聚合操作:
比如说: 要分别按照 年 月 日 小时进行统计总访问量, 此时可以先按照小时统计总访问量 , 后的日 月 年可以在小时的基础上进行累加统计即可, 这样效率比较高
思考, 访问咨询主题中, 是否可以进行提前聚合呢? 不能
在此看板中, 计算指标的 先 去重 在统计个数
小案例:
2020-10-10 15 s01
2020-10-10 15 s02
2020-10-10 16 s01
2020-10-10 16 s03
2020-10-11 10 s02
2020-10-11 11 s04
统计, 每个小时有几个用户数据呢?
2020-10-10 15 2
2020-10-10 16 2
2020-10-11 10 1
2020-10-11 11 1
统计, 每天有几个用户呢?
正确结果:
2020-10-10 3
2020-10-11 2
但是, 如果使用每个小时的统计结果, 来计算:
2020-10-10 4
2020-10-11 2
此时, 会发现有问题了....
DWS层: 业务层
指标: 访问量
维度:
固有维度:
时间维度: 年 季度 月 天 小时
产品属性维度:
总访问量
地区维度
来源渠道维度
搜索来源维度
受访页面维度
开发需求: 共计有 25个开发需求
1) 统计每年 的总访问量
2) 统计 每年 每季度的总访问量
3) 统计 每年 每季度 每月的总访问量
.....
1) 统计每年 各个地区的总访问量
2) 统计每年每季度 各个地区总访问量
....
1) 统计每年各个来源渠道的总访问量数据
2) 统计每年每季度各个来源渠道的总访问量数据
....
....
在DWS层, 需要将每一个需求的结果统计出来, 然后存储在DWS层 , 针对每一个指标, 构建一个结果表, 存储其所有的结果
DWS层表:
组成部分:
指标统计结果字段 + 维度字段 + 业务查询字段(time_type,group_type,time_str)
最终组合下DWS层字段:
sid_total,sessionid_total,ip_total,area,origin_channel,seo_source
from_url, hourinfo,time_type,group_type,time_str
yearinfo, quarterinfo,monthinfo,dayinfo,
-------------------------------------
指标: 咨询量
维度:
固有维度:
时间维度: 年 季度 月 天 小时
产品属性维度:
总咨询量
地区维度
来源渠道维度
DWS层表:
组成部分:
指标统计结果字段 + 维度字段 + 业务查询字段(time_type,group_type,time_str)
最终组合下DWS层字段:
sid_total,sessionid_total,ip_total,area,origin_channel
hourinfo,time_type,group_type,time_str
yearinfo, quarterinfo,monthinfo,dayinfo,
APP层: 数据应用层
思考: 是否还需要对DWS层数据进行统计? ---> 是否在DWS层以及将需要的结果统计出来了?此时发现, 需要要求安装各个维度统计结果此时在DWS层以及统计完成了, 此时不需要在继续统计了, 所以不需要app层如果说, 需要计算比率 , 咨询率 此时可能需要app层
DIM层: 维表层
默认格式,行式存储。可结合Gzip、Bzip2使用(系统自动检查,执行查询时自动解压),但使用这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。并且反序列化过程中,必须逐个字符判断是不是分隔符和行结束符,性能较差。
使用ORC文件格式可以提高hive读、写和处理数据的能力。ORCFile是RCFile的升级版。
在ORC格式的hive表中,数据按行分块,每块按列存储。结合了行存储和列存储的优点。记录首先会被横向的切分为多个stripes,然后在每一个stripe内数据以列为单位进行存储,所有列的内容都保存在同一个文件中。
每个stripe的默认大小为256MB,相对于RCFile每个4MB的stripe而言,更大的stripe使ORC可以支持索引,数据读取更加高效。
优点:压缩率比较高;hadoop本身支持,在应用中处理gzip格式的文件就和直接处理文本一样。
缺点:压缩性能一般。
优点:高速压缩速度和合理的压缩率。
缺点:压缩率比zlib要低;hadoop本身不支持,需要安装(CDH版本已自动支持,可忽略)。
因为ORCFILE的压缩快、存取快,而且拥有特有的查询优化机制,所以系统采用ORCFILE存储格式(RCFILE升级版),压缩算法采用orc支持的ZLIB和SNAPPY。
在ODS数据源层,因为数据量较大,可以采用orcfile+ZLIB的方式,以节省磁盘空间;
而在计算的过程中(DWD、DWM、DWS、APP),为了不影响执行的速度,可以浪费一点磁盘空间,采用orcfile+SNAPPY的方式,提升hive的执行速度。
存储空间足够的情况下,推荐采用SNAPPY压缩。
在项目中:
ODS层: ZLIB+ORC
其他层次: SNAPPY + ORC
说明: 如果存储空间比较宽裕的, 建议在hive中建表时都可以采用snappy压缩方案
开发步骤共包含两大过程:全量过程和增量过程。
全量过程是在首次建库时,需要对OLTP应用(Mysql)中的全量数据进行采集、清洗和统计计算。历史数据量可能会非常大,远远超出了增量过程。在执行时需要进行针对性的优化配置并采用分批执行。
增量过程是在全量过程之后进行的,大多采用的是T+1模式。
全量执行完毕后,对OLTP每天的新增数据和更新数据要进行同步,如果还是对全量数据进行分析,效率会非常低下。增量数据只有一天的量,采集、清洗和统计的效率相对于全量过程会有很大提升。
什么是T+1?
这种说法来源于股票交易:
T+0,是国际上普遍使用的一种证劵度(或期货)交易制度。凡在证劵(或期货)成交日当天办理好证劵(或期货)和价款清算交割手续的交易制度,就称为T+0交易。通俗说,就是当天买入的证道劵(或期货)在当天就可以卖出。
T+1是一种股票交易制度,即当日买进的股票,要到下一个交易日才能卖出。“T”指交易登记日,“T+1”指登记日的次日。
我们知道传统的OLTP数据库(Mysql)一般都具有索引和表分区的功能,通过表分区能够在特定的区域检索数据,减少扫描成本,在一定程度上提高查询效率,我们还可以通过建立索引进一步提升查询效率。在Hive数仓中也有索引和分区的概念。
为了对表进行合理的管理以及提高查询效率,Hive可以将表组织成“分区”。
分区是表的部分列的集合,可以为频繁使用的数据建立分区,这样查找分区中的数据时就不需要扫描全表,这对于提高查找效率很有帮助。
分区是一种根据“分区列”(partition column)的值对表进行粗略划分的机制。Hive中每个分区对应着表很多的子目录,将所有的数据按照分区列放入到不同的子目录中去。
庞大的数据集可能需要耗费大量的时间去处理。在许多场景下,可以通过分区的方法减少每一次扫描总数据量,这种做法可以显著地改善性能。
数据会依照单个或多个列进行分区,通常按照时间、地域或者是商业维度进行分区。
比如电影表,分区的依据可以是电影的种类和评级,另外,按照拍摄时间划分可能会得到均匀的结果。
为了达到性能表现的一致性,对不同列的划分应该让数据尽可能均匀分布。最好的情况下,分区的划分条件总是能够对应where语句的部分查询条件,这样才能充分利用分区带来的性能优势。
Hive的分区使用HDFS的子目录功能实现。每一个子目录包含了分区对应的列名和每一列的值。但是由于HDFS并不支持大量的子目录,这也给分区的使用带来了限制。我们有必要对表中的分区数量进行预估,从而避免因为分区数量过大带来一系列问题。
Hive查询通常使用分区的列作为查询条件。这样的做法可以指定MapReduce任务在HDFS中指定的子目录下完成扫描的工作。HDFS的文件目录结构可以像索引一样高效利用。
Hive(Inceptor)分区包括静态分区和动态分区。根据插入时是否需要手动指定分区可以分为:
创建静态分区
CREATE [EXTERNAL] TABLE <table_name>
(<col_name> <data_type> [, <col_name> <data_type> ...])
-- 指定分区键和数据类型
PARTITIONED BY (<partition_key> <data_type>, ...)
[ROW FORMAT <row_format>]
[STORED AS TEXTFILE|ORC|CSVFILE]
[LOCATION '' ]
[TBLPROPERTIES ('' ='' , ...)];
栗子:--分区字段主要是时间,按年分区
CREATE TABLE device_open (
deviceid varchar(50),
...
)
PARTITIONED BY (year varchar(50))
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
写入数据
-- 覆盖写入
INSERT OVERWRITE TABLE <table_name>
PARTITION (<partition_key>=<partition_value>[, <partition_key>=<partition_value>, ...])
SELECT <select_statement>;
-- 追加写入
INSERT INTO TABLE <table_name>
PARTITION (<partition_key>=<partition_value>[, <partition_key>=<partition_value>, ...])
SELECT <select_statement>;
栗子:insert overwrite table device_open partition(year=’2020’)
select
...,
original_device_open.month as month,
original_device_open.day as day,
original_device_open.hour as hour
FROM original_device_open
创建动态分区
--分区字段主要是时间,分为年,月,日,时
CREATE TABLE device_open (
deviceid varchar(50),
...
)
PARTITIONED BY (year varchar(50), month varchar(50), day varchar(50), hour varchar(50))
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
-- 开启动态分区支持,并开启非严格模式
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
insert overwrite table device_open partition(year,month,day,hour)
select
...,
original_device_open.year as year,
original_device_open.month as month,
original_device_open.day as day,
original_device_open.hour as hour
FROM original_device_open
一张表可同时被静态和动态分区键分区,只是动态分区键需要放在静态分区键的后面(因为HDFS上的动态分区目录下不能包含静态分区的子目录)。
静态分区键要用
指定分区值;动态分区只需要给出分区键名称
。
spk 即静态分区static partition key, dpk 即动态分区dynamic partition key。
比如:
insert overwrite table device_open partition(year='2017',month='05',day,hour)
select
...,
original_device_open.day as day,
original_device_open.hour as hour
FROM original_device_open
where original_device_open.year='2017' and original_device_open.month='05'
partition(year=‘2017’, month=‘05’, day, hour),year和month是静态分区字段,day和hour是动态分区字段,这里指将2017年5月份的数据插入分区表,对应底层的物理操作就是将2017年5月份的数据load到hdfs上对应2017年5月份下的所有day和hour目录中去。
注意混用的情况下,静态分区的上层必须也是静态分区,如果partition(year, month, day=’05’, hour=’08’),则会报错:FAILED: SemanticException [Error 10094]: Line 1:50 Dynamic partition cannot be the parent of a static partition ‘‘day’’。
注意,如果个人电脑性能不好,出现因为动态分区而导致的内存溢出问题,可以设置hive.optimize.sort.dynamic.partition进行避免:
设置为true后,当启用动态分区时,reducer仅随时保持一个记录写入程序,从而降低对 reducer产生的内存压力。但同时也会使查询性能变慢。
分区表的作用: 提升查询的性能,为什么说分区表可以提升查询性能呢?
原因:
分区表可以将数据按照分区字段将其划分到多个文件夹中, 在查询的时候, 根据分区字段查询, 此时hive回到指定分区目录下查询数据, 不需要在查询其他目录, 从而可以减少查询数据的扫描量, 从而提升效率
所以说 在hive中构建表的时候, 一般都是构建分区表
思考: 构建分区表, 如何向分区表添加数据
方案一: 静态分区(人为指定分区的值)
格式:
1) load data [local] inpath '路径' into|overwrite table 表名 partition(分区字段1=值1, 分区字段2=值2,...)
2) insert into|overwrite table 表名 partition(分区字段1=值1,分区字段2=值2....) +select ....
方案二: 动态分区(一次性向表中添加多个分区)
格式:
insert into|overwrite table 表名 partition(分区字段1,分区字段2....) +select ....
注意: 如果使用动态分区, 必须满足以下条件
1) 必须配置以下参数:
set hive.exec.dynamic.partition=true; 开启动态分区支持
set hive.exec.dynamic.partition.mode=nonstrict; 开启非严格模式
2) select查询语句结果最后面必须是分区字段,而且要保证顺序
方案三: 动静混合
格式:
insert into|overwrite table 表名 partition(分区字段1=值1,分区字段2,分区字段3....) +select ....
注意: 如果使用动静混合分区, 必须满足以下条件
1) 必须配置以下参数:
set hive.exec.dynamic.partition=true; 开启动态分区支持
set hive.exec.dynamic.partition.mode=nonstrict; 开启非严格模式
2) select查询语句结果最后面必须是动态分区字段,而且要保证顺序
优化动态分区配置:
主要作用:
当电脑内存资源不足时候, 可以开启此参数, 一旦开启, 整个hive翻译MR只会保持一个输出reduce, 从而降低资源的占用情况, 保证正常执行
弊端: 执行效率会降低
指标:访问客户量是单位时间内访问网站的去重后客户数量,以天为单位显示访问客户。
维度:
事实表的数据就是指标数据,访问客户量指标的事实表就是我们的客户访问表。而维度数据都包含在事实表中,没有需要额外关联的维度表。
数据库命名统一加上前缀itcast,在实际场景中,将此前缀替换为系统的简称即可。比如:edu_ods、edu_dwd、edu_dws等。
从咨询系统OLTP数据库(Mysql)的web_chat_ems_20XX_XX等月表中抽取的原始数据;
离线数仓大多数的场景都是T+1,为了便于后续的DW层清洗数据时,快速获取昨天的数据,ODS模型要在原始mysql表的基础之上增加starts_time抽取日期字段,并且可以使用starts_time字段分区以提升查询的性能。
建库:
-- 构建ODS的库
CREATE DATABASE IF NOT EXISTS `itcast_ods`;
建表:web_chat_ems
--写入时压缩生效
set hive.exec.orc.compression.strategy=COMPRESSION;
CREATE EXTERNAL TABLE IF NOT EXISTS itcast_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_match 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 '系统名称')
comment '访问会话信息表'
PARTITIONED BY(starts_time STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
location '/user/hive/warehouse/itcast_ods.db/web_chat_ems_ods'
TBLPROPERTIES ('orc.compress'='ZLIB');
建表:web_chat_text_ems
CREATE EXTERNAL TABLE IF NOT EXISTS itcast_ods.web_chat_text_ems (
id INT COMMENT '主键来自MySQL',
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 '历史访问记录'
) comment 'EMS-PV测试表'
PARTITIONED BY(start_time STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
location '/user/hive/warehouse/itcast_ods.db/web_chat_text_ems_ods'
TBLPROPERTIES ('orc.compress'='ZLIB');
维度:
建库:
-- 构建DWD的库
CREATE DATABASE IF NOT EXISTS `itcast_dwd`;
将ODS层数据,进行清洗转换,并且将web_chat_ems主表和web_chat_text_ems附表的内容根据id合并在一起。
数据粒度保持不变。
数据清洗:空数据、不满足业务需求的数据处理。
数据转换:数据格式和数据形式的转换,比如时间类型可以转换为同样的展现形式“yyyy-MM-dd HH:mm:ss”或者时间戳类型,金钱类型的数据可以统一转换为以元为单位或以分为单位的数值。
建表:
create table if not exists itcast_dwd.visit_consult_dwd(
session_id STRING comment '七陌sessionId',
sid STRING comment '访客id',
create_time bigint comment '会话创建时间',
seo_source STRING comment '搜索来源',
ip STRING comment 'IP地址',
area STRING comment '地域',
msg_count int comment '客户发送消息数',
origin_channel 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 '历史访问记录',
hourinfo string comment '小时',
quarterinfo string comment '季度'
)
comment '访问咨询DWD表'
partitioned by(yearinfo String, monthinfo String, dayinfo string)
row format delimited fields terminated by '\t'
stored as orc
location '/user/hive/warehouse/itcast_dwd.db/visit_consult_dwd'
tblproperties ('orc.compress'='SNAPPY');
在DWD层的基础上,按照业务的要求进行统计分析;时间和业务属性三个维度分类,可以在模型中增加对应的属性标识:
建库:
-- 构建DWS的库
CREATE DATABASE IF NOT EXISTS `itcast_dws`;
建表:
CREATE TABLE IF NOT EXISTS itcast_dws.visit_dws (
sid_total INT COMMENT '根据sid去重求count',
sessionid_total INT COMMENT '根据sessionid去重求count',
ip_total INT COMMENT '根据IP去重求count',
area STRING COMMENT '区域信息',
seo_source STRING COMMENT '搜索来源',
origin_channel STRING COMMENT '来源渠道',
hourinfo STRING COMMENT '创建时间,统计至小时',
quarterinfo STRING COMMENT '季度',
time_str STRING COMMENT '时间明细',
from_url STRING comment '会话来源页面',
groupType STRING COMMENT '产品属性类型:1.地区;2.搜索来源;3.来源渠道;4.会话来源页面;5.总访问量',
time_type STRING COMMENT '时间聚合类型:1、按小时聚合;2、按天聚合;3、按月聚合;4、按季度聚合;5、按年聚合;')
comment 'EMS访客日志dws表'
PARTITIONED BY(yearinfo STRING,monthinfo STRING,dayinfo STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
stored as orc
location '/user/hive/warehouse/itcast_dws.db/visit_dws'
TBLPROPERTIES ('orc.compress'='SNAPPY');
CREATE TABLE IF NOT EXISTS itcast_dws.consult_dws
(
sid_total INT COMMENT '根据sid去重求count',
sessionid_total INT COMMENT '根据sessionid去重求count',
ip_total INT COMMENT '根据IP去重求count',
area STRING COMMENT '区域信息',
origin_channel STRING COMMENT '来源渠道',
hourinfo STRING COMMENT '创建时间,统计至小时',
quarterinfo STRING COMMENT '季度',
time_str STRING COMMENT '时间明细',
groupType STRING COMMENT '产品属性类型:1.地区;2.来源渠道',
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
LOCATION '/user/hive/warehouse/itcast_dws.db/consult_dws'
TBLPROPERTIES ('orc.compress'='SNAPPY');
如果用户需要具体的报表展示,可以针对不同的报表页面设计APP层结构,然后导出至OLAP系统的mysql中。
如果系统使用FineBI,需要通过宽表来进行灵活的展现。则APP层不再进行细化。直接将DWS层导出至mysql即可。
下面关于Hive的优化,皆是基于Hive2.x的版本,对于Hive1.x旧版本的优化机制不再复述(新版本已改善或变更)。
另外新版本中默认为开启状态的优化配置项,在工作中无需修改,也不再复述。
dfs.replication(HDFS)
文件副本数,通常设为3,不推荐修改。
如果测试环境只有二台虚拟机(2个datanode节点),此值要修改为2。
配置项:yarn.nodemanager.resource.cpu-vcores
表示该节点服务器上yarn可以使用的虚拟CPU个数,默认值是8,推荐将值配置与物理CPU线程数相同,如果节点CPU核心不足8个,要调小这个值,yarn不会智能的去检测物理核心数。
表示: 每一个nodemanager对应服务器的cpu核心数为 8
grep 'processor' /proc/cpuinfo | sort -u | wc -l
配置项: yarn.nodemanager.resource.memory-mb | yarn.scheduler.maximum-allocation-mb | yarn.app.mapreduce.am.command-opts
说明:
yarn.nodemanager.resource.memory-mb | yarn.scheduler.maximum-allocation-mb : 内存大小配置一致
yarn.app.mapreduce.am.command-opts : 略小于 上面的配置 0.9 左右