Hive零基础入门最全--不看后悔

Hive零基础入门必看--超级全

  • 概述
  • 数据库与数据仓库的区别
  • Hive的优缺点
  • Hive的特性
          • 针对海量数据的高性能查询和分析系统
          • 类SQL的查询语言
        • HiveQL灵活的扩展性
        • 高扩展性(Scalability)和容错性
        • 与Hadoop其他产品完全兼容
  • 元数据
        • 为什么不使用derby存放元数据
  • 常见表
        • 内部表
            • 常用的内部表语句
        • 外部表
        • 分区表
        • 分桶表
  • 数据类型
  • 函数
      • 数学函数
      • 类型转换函数
      • 日期函数
      • 条件函数
      • 字符串函数
      • 聚合函数
      • explode内置函数
      • 自定义函数
          • **UDF**
          • **UDAF**
          • **UDTF**
  • Hive解决数据倾斜问题
  • Hive的优化
      • map side join
      • join语句优化
      • group by 优化
      • count distinct 优化
      • JVM重利用
      • 启用严格模式
      • 关闭推测执行机制
  • 复杂数据类型
      • 数组类型
      • map类型
      • struct类型
  • 运算符
      • 关系运算符
      • 算数运算符
      • 逻辑运算符
  • 体系结构
  • 流程
  • Hive文件格式

概述

  1. Hive是基于Hadoop的一个数据仓库工具。可以将结构化的数据文件映射为一张表,并提供完整的sql查询功能
  2. 底层是将sql语句转换为MapReduce任务进行运行
  3. Hive提供了一系列的工具,可以用来进行数据提取、转化、加载(ETL Extract-Transform-Load ),这是一种可以存储、查询和分析存储在 Hadoop 中的大规模数据的机制
    本质上是一种大数据离线分析工具

数据库与数据仓库的区别

Hive零基础入门最全--不看后悔_第1张图片

Hive的优缺点

优点:
1. 学习成本低,只要会sql就能用hive
2. 开发效率高,不需要编程,只需要写sql
3. 模型简单,易于理解
4. 针对海量数据的高性能查询和分析
5. HiveQL 灵活的可扩展性(Extendibility)
6. 高扩展性(Scalability)和容错性
7. 与 Hadoop 其他产品完全兼容
缺点:
1. 不支持行级别的增删改
2. 不支持完整的在线事务处理
3.本质上仍然是MR的执行,效率不算高

Hive的特性

针对海量数据的高性能查询和分析系统

由于 Hive 的查询是通过 MapReduce 框架实现的,而 MapReduce 本身就是为实现针对海量数据的高性能处理而设计的。所以 Hive 天然就能高效的处理海量数据。
  
与此同时,Hive 针对 HiveQL 到 MapReduce的翻译进行了大量的优化,从而保证了生成的MapReduce 任务是高效的。在实际应用中,Hive 可以高效的对 TB 甚至 PB级的数据进行处理。

类SQL的查询语言

HiveQL 和 SQL 非常类似,所以一个熟悉SQL 的用户基本不需要培训就可以非常容易的使用 Hive 进行很复杂的查询。

HiveQL灵活的扩展性

除了 HiveQL 自身提供的能力,用户还可以自定义其使用的数据类型、也可以用任何语言自定义 mapper 和 reducer 脚本,还可以自定义函数(普通函数、聚集函数)等。这就赋予了 HiveQL 极大的可扩展性。用户可以利用这种可扩展性实现非常复杂的查询。

高扩展性(Scalability)和容错性

Hive本身并没有执行机制,用户查询的执行是通过 MapReduce 框架实现的。由于MapReduce 框架本身具有高度可扩展(计算能力随 Hadoop 机群中机器的数量增加而线性增加)和高容错的特点,所以 Hive也相应具有这些特点。

与Hadoop其他产品完全兼容

Hive 自身并不存储用户数据,而是通过接口访问用户数据。这就使得 Hive支持各种数据源和数据格式。例如,它支持处理 HDFS 上的多种文件格式(TextFile、SequenceFile 等),还支持处理 HBase 数据库。用户也完全可以实现自己的驱动来增加新的数据源和数据格式。一种理想的应用模型是将数据存储在 HBase 中实现实时访问,而用Hive对HBase 中的数据进行批量分析。

元数据

  1. hive可以管理hdfs上的文件,用表的形式来管理文件数据。而表名、表里有哪些字段,字段类型、哪张表存在哪个数据下等这些表信息,称之为hive的元数据信息
  2. 默认情况下,hive的元数据信息不是存在hdfs上的,而是存在hive自带的derby关系型数据库里的
  3. Hive安装完成之后,通常都需要替换元数据库,目前Hive只支持derby和mysql两种元数据库,需要将元数据库替换为MySQL
    元数据的默认字符集是ISO8859-1

为什么不使用derby存放元数据

  1. derby数据库是一种文件型的数据库,在进入时会检查当前目录下是否有metastore_db文件夹用来存储数据库数据,如果有就直接使用,如果没有就创建,这样一旦换一个目录,元数据就找不到了
  2. derby数据库是一个单用户的数据库,无法支持多用户同时操作,而hive如果使用derby作为元数据库,则也只能支持单用户操作,这就导致在数据量大连接多的情况下会产生大量连接的积压

常见表

内部表

在Hive中建立的一张表(可以直接在表中插入数据或者读取外部文件插入数据)。
内部表删除的时候HDFS中是数据会被删除

常用的内部表语句

Hive零基础入门最全--不看后悔_第2张图片

外部表

利用Hive创建一张表来管理HDFS里某个目录下的文件数据。
外部表可以删除但是HDFS中的数据不会被删除。
Hive零基础入门最全--不看后悔_第3张图片

分区表

可以通过添加指定的字段提高Hive的查询效率,避免了全表遍历。
Hive零基础入门最全--不看后悔_第4张图片

分桶表

实现数据的抽样方便进行数据测试
通过hash分桶算法将数据与分放在不同的桶(hdfs中的文件)中,方便后续获取
分桶表机制默认是不开启的,需要手动开启:set hive.enforce,bucketing=true
分桶表不允许导入外部文件,只能从一张表数据导入
分桶表是内部表,解决了大表之间的join
原理:分桶的原理是根据指定的列的计算hash值模余分桶数量后将数据分开存放。方便数据抽样
Hive零基础入门最全--不看后悔_第5张图片

数据类型

Hive零基础入门最全--不看后悔_第6张图片

函数

数学函数

Hive零基础入门最全--不看后悔_第7张图片

类型转换函数

在这里插入图片描述

日期函数

Hive零基础入门最全--不看后悔_第8张图片

条件函数

Hive零基础入门最全--不看后悔_第9张图片

字符串函数

Hive零基础入门最全--不看后悔_第10张图片

聚合函数

Hive零基础入门最全--不看后悔_第11张图片

explode内置函数

一、概述
	1. explode 命令可以将行数据,按指定规则切分出多行
	2. 用explode做行切分,注意表里只有一列,并且行数据是string类型,因为只有字符类型才能做切分。

二、示例
原始数据:
100,200,300
200,300,500
要求:
要将上面两行数据根据逗号拆分成多行(每个数字占一行)
实现步骤
	1. 上传HDFS,并创建对应的外部表,执行:create external table ex1 (num string) location '/ex';

通过explode指令来做行切分,执行:select explode(split(num,’,’)) from ex1;是根据指定的列的计算hash值模余分桶数量后将数据分开存放。方便数据抽样
Hive零基础入门最全--不看后悔_第12张图片

自定义函数

UDF
import org.apache.hadoop.hive.ql.exec.UDF;
public class ToUpper extends UDF{
    public String evaluate(String str){
        return str.toUpperCase();
    }
}

Hive零基础入门最全--不看后悔_第13张图片
编写UDF函数的时候需要注意一下几点:
a)自定义UDF需要继承org.apache.hadoop.hive.ql.UDF。
b)需要实现evaluate函数,evaluate函数支持重载。

  1. 为了能让mapreduce处理,String要用Text处理。
  2. 将写好的类打成jar包,上传到linux中
  3. 在hive命令行下,向hive注册UDF:add jar /xxxx/xxxx.jar
    在这里插入图片描述
  4. 在hive命令行下,为当前udf起一个名字:create temporary function fname as ‘类的全路径名’;
    e注册UDF:add jar /xxxx/xxxx.jar
    在这里插入图片描述
  5. 之后就可以在hql中使用该自定义函数了。
    在这里插入图片描述
UDAF

多行进一行出,如sum()、min(),用在group by时
1.必须继承
org.apache.hadoop.hive.ql.exec.UDAF(函数类继承)
org.apache.hadoop.hive.ql.exec.UDAFEvaluator(内部类Evaluator实现UDAFEvaluator接口)
2.Evaluator需要实现 init、iterate、terminatePartial、merge、terminate这几个函数
init():类似于构造函数,用于UDAF的初始化
iterate():接收传入的参数,并进行内部的轮转,返回boolean
terminatePartial():无参数,其为iterate函数轮转结束后,返回轮转数据,类似于hadoop的Combiner
merge():接收terminatePartial的返回结果,进行数据merge操作,其返回类型为boolean

UDTF

UDTF(User-Defined Table-Generating Functions) 用来解决 输入一行输出多行(On-to-many maping) 的需求。

Hive解决数据倾斜问题

什么是数据倾斜以及数据倾斜是怎么产生的?
简单来说数据倾斜就是数据的key的分化严重不均匀,造成一部分数据很多,一部分数据很少的局面。
业务逻辑造成的数据倾斜会多很多,日常使用过程中,容易造成数据倾斜的原因可以归纳为几点:
1)group by
2)distinct count(distinct xx)
3)join

Hive的优化

map side join

  1. mapJoin的主要意思就是,当连接的两个表是一个比较小的表和一个特别大的表的时候,可以把比较小的table直接放到内存中去,然后再对比较大的表格进行map操作,此时join就发生在map操作的时候,每当扫描一个大的table中的数据,就要去去查看小表的数据,哪条与之相符,继而进行连接。这里的join并不会涉及reduce操作。map端join的优势就是在于没有shuffle,在实际的应用中,设置方式:set hive.auto.convert.join=true;
  2. hive有一个参数:hive.mapjoin.smalltable.filesize,默认值是25mb(其中一个表大小小于25mb时,自动启用mapjoin)
  3. 要求:在hive做join时,要求小表在前(左)

join语句优化

例如:order表有1000条数据,customer表有1000条数据 mid=uid有300条,m.dt=‘20160801’有100条数据
优化前:select m.cid,u.id form order m join customer u on m.cid=u.id where m.dt=’20160801’;
解析:order表先和customer表进行全外连接查询出mid=uid的300条数据,再从三表条数据中查询出100条符合条件的数据
(10001000)+300=1000300=一百万零三百
优化后:select m.cid,u.id from (select cid from order where dt=’20160801’)m join customer u on m.cid = u.id
解析:现在order表中查询出dt=‘20160801’的数据,在进行m表和customer表的全外连接查询出m.cid=u.id的数据
1000+(100
1000)=101000=十万零一千

group by 优化

调优参数:set hive.groupby.skewindata=true;

select count(w) from words group by w;
假设这种方式是对单词的个数进行统计
group by - 实际上对应了MapReduce中的Partition操作 - group by出来有多少个group就意	味着有多少个分区,每一个分区要对应一个ReduceTask
hello hadoop
hello hive
hello flume source
hello hadoop yarn

hello - ReduceTask
hadoop - ReduceTask
flume - ReduceTask
100G --- 60G 3G flume 5G Hadoop ...
在给定这些数据中,hello的数量偏多,flume的数据量偏少,那就意味着处理hello的ReduceTask要计算的总量要偏多 --- 数据倾斜
分而治之

数据倾斜时负载均衡,当选项设定为true,生成的查询计划会有两个MRJob。第一个MRJob 中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的GroupBy Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MRJob再根据预处理的数据结果按照GroupBy Key分布到Reduce中(这个过程可以保证相同的GroupBy Key被分布到同一个Reduce中),最后完成最终的聚合操作
由上面可以看出起到至关重要的作用的其实是第二个参数的设置,它使计算变成了两个mapreduce,先在第一个中在 shuffle 过程 partition 时随机给 key 打标记,使每个key 随机均匀分布到各个 reduce 上计算,但是这样只能完成部分计算,因为相同key没有分配到相同reduce上,所以需要第二次的mapreduce,这次就回归正常 shuffle,但是数据分布不均匀的问题在第一次mapreduce已经有了很大的改善,因此基本解决数据倾斜

hive.groupby.skewindata=true:数据倾斜时负载均衡,当选项设定为true,生成的查询计划会有两个MRJob。第一个MRJob 中,Map的输出结果集合会随机分布到Reduce中,每个Reduce做部分聚合操作,并输出结果,这样处理的结果是相同的GroupBy Key有可能被分发到不同的Reduce中,从而达到负载均衡的目的;第二个MRJob再根据预处理的数据结果按照GroupBy Key分布到Reduce中(这个过程可以保证相同的GroupBy Key被分布到同一个Reduce中),最后完成最终的聚合操作。
由上面可以看出起到至关重要的作用的其实是第二个参数的设置,它使计算变成了两个mapreduce,先在第一个中在 shuffle 过程 partition 时随机给 key 打标记,使每个key 随机均匀分布到各个 reduce 上计算,但是这样只能完成部分计算,因为相同key没有分配到相同reduce上,所以需要第二次的mapreduce,这次就回归正常 shuffle,但是数据分布不均匀的问题在第一次mapreduce已经有了很大的改善,因此基本解决数据倾斜。

count distinct 优化

优化前:select count(distinct id )from tablename
去重:distinct - 无论有多少个map,在map阶段无法进行合并(combine) - 需要全部的值都发往Reduce,然后在Reduce才真正进行去重 - 如果不指定默认只有一个ReduceTask - set mapreduce.reduce.tasks = 5
聚合:因为聚合函数的参与,为了保证最后的结果会全部聚合在一块,强制只存在一个ReduceTask
优化后:select count() from (select distinct id from tablename)tmp;
虽然无法在map端去重,但是可以设置多个ReduceTask
分析:
a. 优化前
i. 由于对id=引入了distinct操作,所以在Map阶段无法利用combine对输出结果去消重,必须将id作为key输出
ii. 在reduce阶段再对来自于不同的MapTask的结果进行消重,计入最终统计值
iii. 由于ReduceTask的数量默认为1,所以导致MapTask的所有结果都只能由这一个ReduceTask处理,这就使得ReduceTask的执行效率成为整个任务的瓶颈
虽然在使用hive的时候可以通过set mapred.reduce.tasks设置ReduceTask的数量,但是Hive在处理COUNT这种“全聚合(full aggregates)”计算时,它会忽略用户指定的Reduce Task数,而强制使用1。
Hive零基础入门最全--不看后悔_第14张图片
b. 优化后:
i. 利用Hive对嵌套语句的支持,将原来一个MapReduce作业转换为两个作业:在第一阶段选出全部的非重复id,在第二阶段再对这些已消重的id进行计数
ii. 在第一阶段我们可以通过增大Reduce的并发数,并发处理Map输出
iii. 在第二阶段,由于id已经消重,因此COUNT(
)操作在Map阶段不需要输出原id数据,只输出一个合并后的计数即可。这样即使第二阶段Hive强制指定一个Reduce Task,极少量的Map输出数据也不会使单一的Reduce Task成为瓶颈
iv. 这一优化使得在同样的运行环境下,优化后的语句执行只需要原语句20%左右的时间
Hive零基础入门最全--不看后悔_第15张图片

JVM重利用

  1. 设置方式:set mapred.job.reuse.jvm.num.tasks=20(默认是1个) 减少jvm子进程的创建与销毁
  2. JVM重用是hadoop调优参数的内容,对hive的性能具有非常大的影响,特别是对于很难避免小文件的场景或者task特别多的场景,这类场景大多数执行时间都很短。这时JVM的启动过程可能会造成相当大的开销,尤其是执行的job包含有成千上万个task任务的情况
  3. JVM重用可以使得一个JVM进程在同一个JOB中重新使用N次后才会销毁。

启用严格模式

简单来说限制了一些字段以做到优化效果
1. 用户可以通过 set hive.mapred.mode=strict 来设置严格模式,改成unstrict则为非严格模式
2. 在严格模式下,用户在运行如下query的时候会报错:
1. 分区表的查询没有使用分区字段来限制
2. 使用了order by 但没有使用limit语句(如果不使用limit,会对查询结果进行全局排序,消耗时间长)
3. 产生了笛卡尔积

关闭推测执行机制

  1. 简单来说就是在数据偏移的情况下如果其他分片运算结束,数据量比较大的分片计算到一定时间,会认为这个job执行失败,就会产生一个相同的job在另外一个节点上执行,造成资源浪费。
    通常在测试环境下机会确定应用程序是否跑通,如果还加上推测执行,那么在数据分片本来就会发生数据倾斜,执行执行时间就是比其他的时间长,那么hive就会把这个执行时间长的job当作运行失败,继而又产生一个相同的job去运行,造成资源的浪费。可通过如下设置关闭推测执行:
    set mapreduce.map.speculative=false
    set mapreduce.reduce.speculative=false
    set hive.mapred.reduce.tasks.speculative.execution=false

复杂数据类型

数组类型

案例一
原始数据:
100,200,300
200,300,500
建表语句:
create external table ex(vals array) row format delimited fields terminated by ‘\t’ collection items terminated by ‘,’ location ‘/ex’;
查询每行数组的个数,查询语句:
select size(vals) from ex;
注:hive 内置函数不具备查询某个具体行的数组元素。需要自定义函数来实现,但这样的需求在实际开发里很少,所以不需要在意。
案例二
原始数据:
100,200,300 tom,jary
200,300,500 rose,jack
建表语句:
create external table ex1(info1 array,info2 array) row format delimited fields terminated by ‘\t’ collection items terminated by ‘,’ location ‘/ex’;
结果
在这里插入图片描述

map类型

原始数据:
tom,23
rose,25
jary,28
建表语句:
create external table m1 (vals map) row format delimited fields terminated by ‘\t’ map keys terminated by ‘,’ location ‘/map’;
查询语句:
select vals[‘tom’] from m1;
在这里插入图片描述
案列二
原始数据:
tom 192.168.234.21
rose 192.168.234.21
tom 192.168.234.22
jary 192.168.234.21
tom 192.168.234.24
tom 192.168.234.21
rose 192.168.234.21
tom 192.168.234.22
jary 192.168.234.21
tom 192.168.234.22
tom 192.168.234.23
建表语句 :
create external table ex (vals map) row format delimited fields terminated by ‘\t’ map keys terminated by ’ ’ location ‘/ex’;
注意:map类型,列的分割符必须是\t
查询语句
select vals[‘tom’] from ex where vals[‘tom’] is not null;
如果想做去重工作,可以调用distinct内置函数
select distinct(ip) from (select vals[‘tom’] ip from ex where vals[‘tom’] is not null)ex1; 或者select distinct(vals[‘tom’]) from m2 where vals[‘tom’] is not null;

struct类型

原始数据:
tom 23
rose 22
jary 26
建表语句:
create external table ex (vals structname:string,age:int)row format delimited collection items terminated by ’ ’ location ‘/ex’;
查询语句:
select vals.age from ex where vals.name=‘tom’;

运算符

关系运算符

Hive零基础入门最全--不看后悔_第16张图片

算数运算符

Hive零基础入门最全--不看后悔_第17张图片

逻辑运算符

Hive零基础入门最全--不看后悔_第18张图片

体系结构

Hive零基础入门最全--不看后悔_第19张图片
1. 用户接口主要有三个:CLI,JDBC 和 WUI
a. CLI,最常用的模式。实际上在>hive 命令行下操作时,就是利用CLI用户接口
b. JDBC,通过java代码操作,需要启动hiveserver,然后连接操作
2. Metastore
Hive将元数据存储在数据库中,如mysql、derby。Hive中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等
3. 解释器(complier)、优化器(optimizer)、执行器(executor)组件
这三个组件用于:HQL语句从词法分析、语法分析、编译、优化以及查询计划的生成。生成的查询计划存储在HDFS中,并在随后有MapReduce调用执行
4. Hadoop
Hive的数据存储在HDFS中,大部分的查询、计算由MapReduce完成

流程

Hive零基础入门最全--不看后悔_第20张图片
1. 通过客户端提交一条Hql语句
2. 通过complier(编译组件)对Hql进行词法分析、语法分析。在这一步,编译器要知道此hql语句到底要操作哪张表
3. 去元数据库找表信息
4. 得到信息
5. complier编译器提交Hql语句分析方案
6. 执行流程
a. executor 执行器收到方案后,执行方案(DDL过程)。在这里注意,执行器在执行方案时,会进行判断:如果当前方案不涉及到MR组件,比如为表添加分区信息、比如字符串操作等,比如简单的查询操作等,此时就会直接和元数据库交互,然后去HDFS上去找具体数据;如果方案需要转换成MR job,则会将job 提交给Hadoop的JobTracker
b. MR job完成,并且将运行结果写入到HDFS上
c. 执行器和HDFS交互,获取结果文件信息
如果客户端提交Hql语句是带有查询结果性的,则会发生:7-8-9步,完成结果的查询。

Hive文件格式

概述
hive文件存储格式包括以下几类:
1、TEXTFILE
2、SEQUENCEFILE
3、RCFILE
4、ORCFILE
5、Parquet

其中TEXTFILE为默认格式,建表时不指定默认为这个格式,导入数据时会直接把数据文件拷贝到hdfs上不进行处理。

SEQUENCEFILE,RCFILE,ORCFILE格式的表不能直接从本地文件导入数据,数据要先导入到textfile格式的表中, 然后再从表中用insert导入SequenceFile,RCFile,ORCFile表中。

一、TEXTFILE
默认格式,数据不做压缩,磁盘开销大,数据解析开销大。
可结合Gzip、Bzip2使用(系统自动检查,执行查询时自动解压),但使用这种方式,hive不会对数据进行切分,从而无法对数据进行并行操作。
示例:
create table if not exists textfile_table(
site string,
url string,
pv bigint,
label string)
row format delimited
fields terminated by ‘\t’
stored as textfile;
插入数据操作:
set hive.exec.compress.output=true;
set mapred.output.compress=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec;
insert overwrite table textfile_table select * from textfile_table;

二、SEQUENCEFILE
SequenceFile是Hadoop API提供的一种二进制文件支持,其具有使用方便、可分割、可压缩的特点。
SequenceFile支持三种压缩选择:NONE,RECORD,BLOCK。Record压缩率低,一般建议使用BLOCK压缩。
示例:
create table if not exists seqfile_table(
site string,
url string,
pv bigint,
label string)
row format delimited
fields terminated by ‘\t’
stored as sequencefile;
插入数据操作:
set hive.exec.compress.output=true;
set mapred.output.compress=true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.GzipCodec;
set io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec;
SET mapred.output.compression.type=BLOCK;
insert overwrite table seqfile_table select * from textfile_table;
,完成结果的查询。

你可能感兴趣的:(Hive)