Data Warehouse,(DW或DWH)。
1、目的:
2、主要特征:
面向主题:一般都是有一定的目的进行构建数据仓库
集成性:将所有用到的数据都会集成到一起去
非易失性:数据仓库里面的数据一般都不会改变(数据仓库是用于正确的记录已经发生的事实)
时变性:随着时间的发展,数据仓库分析的手段也会改变
一个是用于分析数据一个是用于保证事务性
数据仓库的出现不是要取代数据库,也不是一个大型的数据库的集合
(1)数据库是面向事务的设计,数据仓库是面向主题设计的。
(2)数据库一般存储业务数据,数据仓库存储的一般是历史数据。
(3)数据库是为捕获数据而设计,数据仓库是为分析数据而设计。
(3)数据库设计是尽量避免冗余,一般针对某一业务应用进行设计,比如一张简单的User表,记录用户名、密码等简单数据即可,符合业务应用,但是不符合分析。
数据仓库在设计是有意引入冗余,依照分析需求,分析维度、分析指标进行设计。
实际是联机事务处理 OLTP(On-Line Transaction Processing,)与 联机分析处理 OLAP(On-Line Analytical Processing) 的区别。
传统的数据库系统,作为数据管理的主要手段,主要用于操作型处理。
分析型处理,叫联机分析处理 OLAP,一般针对某些主题的历史数据进行分析,支持管理决策
数据仓库,是在数据库已经大量存在的情况下,为了进一步挖掘数据资源、为了决策需要而产生的,它决不是所谓的“大型数据库”。
(1)源数据层(ODS): 主要是用于保管我们的原始数据的
(2)数据仓库层(DW):主要是用于面向数据分析的,大部分的工作,都是在这一层,写sql
(3)数据应用层(DA或APP):主要用于数据的报表展示
ETL:数据仓库,从各数据源获取数据及在数据仓库内的数据,转换和流动都可以认为是ETL(抽取Extra, 转化Transfer, 装载Load)的过程,
ETL是数据仓库的流水线,也可以认为是数据仓库的血液,它维系着数据仓库中数据的新陈代谢,而数据仓库日常的管理和维护工作的大部分精力就是保持ETL的正常和稳定。
数据仓库的数据来源于不同的源数据,并提供多样的数据应用,数据自下而上流入数据仓库后向上层开放应用,而数据仓库只是中间集成化数据管理的一个平台。
用空间换时间,通过大量的预处理来提升应用系统的用户体验(效率),因此数据仓库会存在大量冗余的数据;
不分层的话,如果源业务系统的业务规则发生变化将会影响整个数据清洗过程,工作量巨大。
通过数据分层管理,可以简化数据清洗的过程,
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供类SQL查询功能。
本质是:将SQL转换为MapReduce任务进行运算,底层由HDFS来提供数据的存储,
说白了hive可以理解为一个将SQL转换为MapReduce的任务的工具,甚至更进一步可以说hive就是一个MapReduce的客户端
mr代码非常复杂的通过hive大大的简化了mr的开发,基本上hive可以解决90%的企业开发需求,hive就是mr的一个客户端,没有集群
底层的hadoop:数据存储hdfs,数据的计算mr,运行在yarn上面的
怎么把hive翻译成的mr的
主要就是通过解析器的,就是将sql语法解析成为mr的任务
解析器:主要就是用于解析sql语法
编译器:将解析之后的sql语法进行编译成为MR的任务
优化器:有一定的优化功能,自动的会对我们写的sql语句进行调优,调优的功能有限的
执行器:提交mr的任务到yarn上面去执行的
每执行一次查询,就会有对应的mr任务执行吗?
不一定的,有些查询,不需要mr的参与
hive优缺点:
优点
(1)操作接口采用类SQL语法,提供快速开发的能力(简单、容易上手)。
(2)避免了去写MapReduce,减少开发人员的学习成本。
(3)Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
缺点
(1)Hive 不支持记录级别的增删改操作
(2)Hive 的查询延迟很严重
(3)Hive 不支持事务
(1)CLI(hive shell):bin/hive
(2)JDBC/ODBC(java访问hive):
(3)WEBUI(浏览器访问hive)
(4)hive 命令行
使用hive -e sql语句 来执行hql语句;
hive cli命令窗口查看本地文件系统
hive cli命令窗口查看HDFS文件系统
hive客户端jdbc操作
SQL语言共分为四大类:数据查询语言DQL,数据操纵语言DML,数据定义语言DDL,数据控制语言DCL。
1. 数据查询语言DQL:SELECT子句,FROM子句,WHERE
2 .数据操纵语言DML:1) 插入:INSERT、2) 更新:UPDATE、3) 删除:DELETE
3. 数据定义语言DDL
来创建数据库中的各种对象-----表、视图、索引、同义词、聚簇等如:
CREATE TABLE/VIEW/INDEX/SYN/CLUSTER表 视图 索引 同义词 簇
DDL操作是隐性提交的!不能rollback
4. 数据控制语言DCL
用来授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等。如:
内部表:
外部表:
分区表:
分桶表:
外部表一般都是用在数据仓库的ODS层
内部表一般都是用在数据仓库的DW层
---数据定义语言DDL
--1、内部表:
use myhive;
create table stu(id int,name string);
insert into stu(id,name) values(1,"zhangsan");
select * from stu;
--2、外部表:
create external table score_stu (s_id string, c_id string,s_score int)
partitioned by (day string) row format delimited fields terminated by '\t'
location '/scoredatas'
--3、分区表:
create table score2 (s_id string,c_id string, s_score int)
partitioned by (year string,month string,day string)
row format delimited fields terminated by '\t';
--4、分桶表
create table myhive.user_buckets_demo(id int, name string)
clustered by(id) into 4 buckets
row format delimited fields terminated by '\t';
--表示按照id进行hashCode取值 % 4 确定每一条数据需要去到哪一个文件里面去
--就是前面的mr当中的分区的操
比较特殊,不能使用load,只能通过insert select方式加载数据
创建表的时候已经创建了文件夹,通过insert select的时候才创建文件
把文件传过去以后不用MSCK REPAIR TABLE吗?
是不是可以在分区的基础上进行分桶?
内部分区表 外部分区表 分区表需要load到对应的分区文件夹下面 然后 msck repair
内部表 外部表 都是可以load
--数据操纵语言DML
--导入数据
--(1)直接导入
insert into table score3 partition(month ='201807') values ('001','002','100');
--(2)load方式
--load数据可以从,本地文件系统加载,或者也可以从hdfs上面的数据进行加载
load data local inpath '/kkb/install/hivedatas/teacher.csv' into table myhive.teacher;
load data inpath '/kkb/hdfsload/hivedatas' overwrite into table myhive.teacher;
--(3)查询导入 insert overwrite select
insert overwrite table score5 partition(month = '201806')
select s_id,c_id,s_score from score;
--(4)查询创建as select
create table score6 as select * from score;
--(5)location指定路径
create external table score7 (s_id string,c_id string,s_score int)
row format delimited fields terminated by '\t'
location '/myscore7';
--导出数据
--(1)insert查询导出
--查询导出本地 insert overwrite local director
insert overwrite local directory '/kkb/install/hivedatas/stu'
select * from stu;
--查询导出hdfs(无local) insert overwrite director
insert overwrite directory '/kkb/hivedatas/stu'
row format delimited fields terminated by ','
select * from stu;
--(2) Hive Shell 命令导出
bin/hive -e 'select * from myhive.stu;' > /kkb/install/hivedatas/student1.txt
--(3)export导出到HDFS
export table myhive.stu to '/kkb/install/hivedatas/stuexport';
数据操纵语言DML
插入一条数据,到表里面去,就是执行了一个mr的程序,生成了一个文件,文件里面就一条数据
--数据操纵语言DML
--alter
--#将stu内部表改为外部表
alter table stu set tblproperties('EXTERNAL'='TRUE');
--#把emp外部表改为内部表
alter table teacher set tblproperties('EXTERNAL'='FALSE');
--#修改表的名称
alter table stu3 rename to stu4;
--#增加列
alter table stu4 add columns(address string);
--数据查询语言DQL
-- select
select * from stu;
select id,name as stuName from stu; -- "as" 列改名
select count(*) cnt from score;
select max(s_score) from score; --- min(s_score) sum(s_score) avg(s_score)
select * from score limit 5;--limit子句用于限制返回的行数。
select * from score where s_score > 60;
--计算每个学生的平均分数 Group By 语句通常会和==聚合函数==一起使用
select s_id,avg(s_score) from score group by s_id;
--求每个学生平均分数大于60的人 having针对=查询结果中的列=发挥作用
select s_id,avg(s_score) as avgScore from score2
group by s_id having avgScore > 60;
--Hive支持通常的SQL JOIN语句,但是只支持等值连接,不支持非等值连接
--inner join(默认) left outer join right outer join full outer join
--根据学生和成绩表,查询学生姓名对应的成绩
select * from stu left join score on stu.id = score.s_id;
--按照学生分数的平均值排序
select s_id,avg(s_score) avgscore from score
group by s_id
order by avgscore desc; --全局排序,只有一个reduce asc默认升序
--条件函数
select if(1=2,100,200) from tableName;--200 if
select coalesce(null,'100','50') from tableName;--100 非空查找函数: COALESCE
--、条件判断函数:CASE
Select case 100 when 50 then 'tom' when 100 then 'mary' else 'tim' end from tableName;
select case when 1=2 then 'tom' when 2=2 then 'mary' else 'tim' end from tableName;
1)Sort By:分区内有序;
2)Order By:全局排序,只有一个Reducer;
3)Distrbute By:类似MR中Partition,进行分区,结合sort by使用。
4) Cluster By:当Distribute by和Sorts by字段相同时,可以使用Cluster by方式。Cluster by除了具有Distribute by的功能外还兼具Sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC。
1、Group By 分组
通常会和==聚合函数==一起使用,
按照一个或者多个列队结果进行分组,
然后对每个组执行聚合操作。
having只用于group by分组统计语句
--求每个学生平均分数大于60的人
select s_id,avg(s_score) as avgScore from score2 group by s_id having avgScore > 60;
2、order by 全局排序
只有一个reduce
asc 升序 (默认);desc 降序
order by 子句在select语句的结尾
--按照学生分数的平均值排序
select s_id,avg(s_score) avgscore from score
group by s_id
order by avgscore desc;
3、sort by 局部排序
每个reducer内部进行排序,对全局结果集来说不是排序
select * from score s
sort by s.s_score;
4、distribute by 分区排序
指定按照哪个字段进行分区 可以自己控制分区的字段
类似MR中partition,采集hash算法,在map端将查询的结果中hash值相同的结果,分发到对应的reduce文件中。
distribute by语句要结合sort by使用,写在 sort by 语句之前
select * from score2
distribute by s_id
sort by s_score;
当distribute by和sort by字段相同时,可以使用cluster by方式
除了distribute by 的功能外,还会对该字段进行排序,所以cluster by = distribute by + sort by
--以下两种写法等价
select * from score
distribute by s_score
sort by s_score;
select * from score2
cluster by s_score;
--创建普通表
create table t_order(
order_number string,
order_price double,
order_time string )
row format delimited fields terminated by '\t';
--创建目标分区表
create table order_dynamic_partition(
order_number string,
order_price double )
partitioned BY(order_time string)
row format delimited fields terminated by '\t';
--向普通表t_order加载数据
load data local inpath '/kkb/install/hivedatas/order_partition.txt'
overwrite into table t_order;
--要想进行动态分区,需要设置参数
//开启动态分区功能
hive> set hive.exec.dynamic.partition=true;
//设置hive为非严格模式
hive> set hive.exec.dynamic.partition.mode=nonstrict;
insert into table order_dynamic_partition partition(order_time)
select order_number,order_price,order_time from t_order;
--查看分区
show partitions order_dynamic_partition;
启动hiveserver2的服务端—引入依赖----代码开发
//获取数据库连接
Connection connection = DriverManager.getConnection(url, "hadoop","");
//定义查询的sql语句
String sql="select * from stu";
try {
PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery();
while (rs.next()){
//获取id字段值
int id = rs.getInt(1);
//获取deptid字段
String name = rs.getString(2);
System.out.println(id+"\t"+name);
}
} catch (SQLException e) {
e.printStackTrace();
dbeaver是一个图形化的界面工具,专门用于与各种数据库的集成,通过dbeaver我们可以与各种数据库进行集成通过图形化界面的方式来操作我们的数据库与数据库表,类似于我们的sqlyog或者navicate
我们使用的版本是6.15这个版本,
Hive参数大全:
https://cwiki.apache.org/confluence/display/Hive/Configuration+Properties
开发Hive应用时,不可避免地需要设定Hive的参数。
设定Hive的参数可以调优HQL代码的执行效率,或帮助定位问题。
对于一般参数,有以下三种设定方式:
参数声明 > 命令行参数 > 配置文件参数(hive)
hive0.9以及之前的版本是不支持传参的 hive1.0版本之后支持 hive -f 传递参数
一般使用 1、hivevar **2、hiveconf ** 来进行参数的传递
hivevar
hiveconf
select * from student
left join score on student.s_id = score.s_id
where score.month = '201807' and score.s_score > 80 and score.c_id = 03;
--定义hive脚本
vim hivevariable.hql
use myhive;
select * from student
left join score on student.s_id = score.s_id
where score.month = ${hiveconf:month} and score.s_score > ${hivevar:s_score} and score.c_id = ${c_id};
--调用hive脚本并传递参数
bin/hive --hiveconf month=201807 --hivevar s_score=80 --hivevar c_id=03 -f hivevariable.hql
系统内置函数
hive> show functions; --1.查看系统自带的函数
hive> desc function upper; --2.显示自带的函数的用法
hive> desc function extended upper;--3.详细显示自带的函数的用法
select round(3.5) from tableName;
--取整函数: round 向下取整函数: floor 向上取整函数: ceil ceiling 取随机数函数: rand
--时间函数
select from_unixtime(1323308943,'yyyyMMdd') from tableName; ---20111208
--UNIX时间戳转日期函数: from_unixtime 日期时间转日期函数: to_date
select day('2011-12-08 10:03:01') from tableName;--8
--日期转年函数: year month day hour minute
select datediff('2012-12-08','2012-05-09') from tableName;--213
--日期转周函数: weekofyear 日期比较函数: datediff 日期增加函数: date_add 日期减少函数: date_sub
--字符串函数
select trim(' abc ') from tableName;--abc
--长度length 反转reverse 字符串连接concat 去空格trim 重复字符串repeat 分割: split
--转大写upper,ucase 转小写lower,lcase 字符串截取substr substring
--url解析parse_url json解析get_json_object
Lateral View通常和UDTF一起出现,为了解决UDTF不允许在select字段的问题。
Multiple Lateral View可以实现类似笛卡尔乘积。
Outer关键字可以把不输出的UDTF的空结果,输出成NULL,防止丢失数据。
reflect函数,可以支持在sql中调用java中的自带函数,秒杀一切udf函数。
--使用java.lang.Math当中的Max,求两列中最大值
select reflect("java.lang.Math","max",col1,col2) from test_udf;
--使用apache commons中的函数,判断是否为数字
select reflect("org.apache.commons.lang.math.NumberUtils","isNumber","123");
对于一些比较复杂的数据求取过程,我们可能就要用到分析函数,分析函数主要用于分组求topN,或者求取百分比,或者进行数据的切片等等,我们都可以使用分析函数来解决
常用的分析函数介绍
Hive 自带了一些函数,比如:max/min等,但是数量有限,自己可以通过自定义UDF来方便的扩展。
根据用户自定义函数类别分为以下三种:
(1)UDF(User-Defined-Function) 一进一出
(2)UDAF(User-Defined Aggregation Function) 聚集函数,多进一出 类似于:count/max/min
(3)UDTF(User-Defined Table-Generating Functions)一进多出 如lateral view explode()
编程步骤:
(1)继承org.apache.hadoop.hive.ql.UDF
(2)需要实现evaluate函数;evaluate函数支持重载;
注意事项
(1)UDF必须要有返回类型,可以返回null,但是返回类型不能为void;
(2)UDF中常用Text/LongWritable等类型,不推荐使用java类型;
在hive当中添加临时函数,需要我们每次进入hive客户端的时候都需要添加以下,
退出hive客户端临时函数就会失效,那么我们也可以创建永久函数来让其不会失效
创建永久函数,与我们的函数进行关联
create function myuppercase as ‘com.kkb.udf.MyUDF’;
1、指定数据库,将我们的函数创建到指定的数据库下面
0: jdbc:hive2://node03:10000>use myhive;
2、使用add jar添加我们的jar包到hive当中来
0: jdbc:hive2://node03:10000>add jar /kkb/install/hive-1.1.0-cdh5.14.2/lib/udf.jar;
3、查看我们添加的所有的jar包
0: jdbc:hive2://node03:10000>list jars;
4、创建永久函数,与我们的函数进行关联
0: jdbc:hive2://node03:10000>create function myuppercase as 'com.kkb.udf.MyUDF';
5、查看我们的永久函数
0: jdbc:hive2://node03:10000>show functions like 'my*';
6、使用永久函数
0: jdbc:hive2://node03:10000>select myhive.myuppercase('helloworld');
7、删除永久函数
0: jdbc:hive2://node03:10000>drop function myhive.myuppercase;
8、查看函数
show functions like 'my*';
压缩模式评价
常见压缩格式
压缩方式 | 压缩比 | 压缩速度 | 解压缩速度 | 是否可分割 |
---|---|---|---|---|
gzip | 13.4% | 21 MB/s | 118 MB/s | 否 |
bzip2 | 13.2% | 2.4MB/s | 9.5MB/s | 是 |
lzo | 20.5% | 135 MB/s | 410 MB/s | 是 |
snappy | 22.2% | 172 MB/s | 409 MB/s | 否 |
压缩格式 | 对应的编码/解码器 |
---|---|
DEFLATE | org.apache.hadoop.io.compress.DefaultCodec |
Gzip | org.apache.hadoop.io.compress.GzipCodec |
BZip2 | org.apache.hadoop.io.compress.BZip2Codec |
LZO | com.hadoop.compress.lzo.LzopCodec |
Snappy | org.apache.hadoop.io.compress.SnappyCodec |
压缩性能的比较
压缩算法 | 原始文件大小 | 压缩文件大小 | 压缩速度 | 解压速度 |
---|---|---|---|---|
gzip | 8.3GB | 1.8GB | 17.5MB/s | 58MB/s |
bzip2 | 8.3GB | 1.1GB | 2.4MB/s | 9.5MB/s |
LZO | 8.3GB | 2.9GB | 49.3MB/s | 74.6MB/s |
开启map输出阶段压缩
开启Reduce输出阶段压缩
当Hive将输出写入到表中时,输出内容同样可以进行压缩。属性hive.exec.compress.output控制着这个功能。用户可能需要保持默认设置文件中的默认值false,这样默认的输出就是非压缩的纯文本文件了。用户可以通过在查询语句或执行脚本中设置这个值为true,来开启输出结果压缩功能。
Hive支持的存储数的格式主要有:
行存储
列存储
TEXTFILE 和 SEQUENCEFILE:的存储格式都是基于行存储的;
ORC 和 PARQUET:是基于列式存储的。
Serde是 Serializer/Deserializer的简写。
hive使用Serde进行行对象的序列与反序列化。最后实现把文件内容映射到 hive 表中的字段数据类型。
Hive 是如何读数据的(类似于 HDFS 中数据的读写操作):
HDFS files –> InputFileFormat –>
Row object –> Serializer –>
hive的SerDe 类型
--通过RegexSerDe 解决多字符分割场景(正则)
create table t2(id int, name string)
row format serde 'org.apache.hadoop.hive.serde2.RegexSerDe' --正则
WITH SERDEPROPERTIES ("input.regex" = "^(.*)\\#\\#(.*)$");
-- 通过MultiDelimitSerDe ==解决多字符分割场景==
create table t1 (id String, name string)
row format serde 'org.apache.hadoop.hive.contrib.serde2.MultiDelimitSerDe'
WITH SERDEPROPERTIES ("field.delim"="##");
1. Fetch抓取:让一些hql语句不用执行MR程序
2. 本地模式:如果数据量小,只启动一个Maptask
3. 表的优化
4.使用分区剪裁、列剪裁
5. 并行执行
6. 严格模式
7.JVM重用
8.开启推测执行机制,(Speculative Execution)
9.数据的压缩
10.避免数据倾斜
1 合理设置Map数
主要的决定因素有:input的文件总个数,input的文件大小,集群设置的文件块大小。
2) 是不是map数越多越好?不是
如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。
3) 是不是保证每个map处理接近128m的文件块,就高枕无忧了?不一定
比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。
针对上面的问题2和3,我们需要采取两种方式来解决:即减少map数和增加map数;
2 小文件合并
在map执行前合并小文件,减少map数:
CombineHiveInputFormat 具有对小文件进行合并的功能(系统默认的格式)
3 复杂文件增加Map数
4 合理设置Reduce数
调整reduce个数 方法一
调整reduce个数 方法二
reduce个数并不是越多越好
理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。
- 3) 是不是保证每个map处理接近128m的文件块,就高枕无忧了?不一定
比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。
- 针对上面的问题2和3,我们需要采取两种方式来解决:即减少map数和增加map数;
2 小文件合并
在map执行前合并小文件,减少map数:
CombineHiveInputFormat 具有对小文件进行合并的功能(系统默认的格式)
3 复杂文件增加Map数
4 合理设置Reduce数
调整reduce个数 方法一
调整reduce个数 方法二
reduce个数并不是越多越好
过多的启动和初始化reduce也会消耗时间和资源;
同时过多的reduce会生成很多个文件,也有可能出现小文件问题