hive学习

主要学习参考:http://lxw1234.com/archives/category/hive,很不错
学习日志1
https://www.cnblogs.com/qingyunzong/p/8707885.html#_label0_0
1、什么hive?

1、Hive 由 Facebook 实现并开源
2、是基于 Hadoop 的一个数据仓库工具
3、可以将结构化的数据映射为一张数据库表
4、并提供 HQL(Hive SQL)查询功能
5、底层数据是存储在 HDFS 上
6、Hive的本质是将 SQL 语句转换为 MapReduce 任务运行
7、使不熟悉 MapReduce 的用户很方便地利用 HQL 处理和计算 HDFS 上的结构化的数据,适用于离线的批量数据计算。

2、 hive有什么优缺点

优点:
  1、可扩展性,横向扩展,Hive 可以自由的扩展集群的规模,一般情况下不需要重启服务 横向扩展:通过分担压力的方式扩展集群的规模 纵向扩展:一台服务器cpu i7-6700k 4核心8线程,8核心16线程,内存64G => 128G
  2、延展性,Hive 支持自定义函数,用户可以根据自己的需求来实现自己的函数
  3、良好的容错性,可以保障即使有节点出现问题,SQL 语句仍可完成执行
缺点:
  1、Hive 不支持记录级别的增删改操作,但是用户可以通过查询生成新表或者将查询结 果导入到文件中(当前选择的 hive-2.3.2 的版本支持记录级别的插入操作)
  2、Hive 的查询延时很严重,因为 MapReduce Job 的启动过程消耗很长时间,所以不能 用在交互查询系统中。
  3、Hive 不支持事务(因为不没有增删改,所以主要用来做 OLAP(联机分析处理),而 不是 OLTP(联机事务处理),这就是数据处理的两大级别)。

3、hive的安装参考:https://www.cnblogs.com/linbingdong/p/5829369.html
4、分区表和分桶表的区别 https://blog.csdn.net/jenrey/article/details/80588493
5、Hive Shell的基本操作

1)进入Hive部署包的bin目录,在命令行输入./hive启动hive cli。
$ cd /user/home/apache-hive-2.2.0-bin/bin
$ ./hive
2)set用来显示和修改变量。如果只使用set,则显示所有变量和属性,包括varconf,env,system和hiveconf。如果加上-v还可以显示hadoop相关的信息。
3)两种创建变量方法
1.在启动hive时,通过–define key=value 或者 –hivevar key=value的形式创建变量
或者
$ hive --define testkey=testvalue //或者使用 --hivevar或-d
hive> set hivevar:testkey; //此处的hivevar:可省略,即直接使用set 
hivevar:testkey=testvalue

2.在启动hive后,通过set创建变量。
     使用set创建  hive> set hivevar:testkey2=testvalue2;
     在Hive处理一条查询语句之前,会将查询语句中的变量替换成相应的值,然后再处理。但是set创建变量时hivevar不可以省略。否
     则,在执行create table语句时,会报错“AILED: ParseException line 1:23 cannot recognize input near ‘$’ ‘{’ ‘label’ in column name or 
      primary key or foreign key”。
     		hive> set hivevar:label=id;  //不能使用set label=id。
		    hive> set label;
		    label=id
		    hive> create table student(${hivevar:label} int, name string);
		    hive> describe student;
		    id                      int                                         
		    name                    string
		    hive> drop table student; //删除测试表student。

4、hiveconf
用于进行hive相关的配置。包含两种方式:
方法1:
Hive启动时,通过–hiveconf配置。比如配置显示当前所在的数据库,该值默认为false。

./hive --hiveconf hive.cli.print.current.db=true
hive (default)>

方法2:
Hive启动后,通过set设置。

hive (default)> hive.cli.print.current.db=true
hive>

5、hive配置文件的参数说明(百度)

1.hive输出格式的配置项是哪个?
2.hive被各种语言调用如何配置?
3.hive提交作业是在hive中还是hadoop中?
4.一个查询的最后一个map/reduce任务输出是否被压缩的标志,通过哪个配置项?
5.当用户自定义了UDF或者SerDe,这些插件的jar都要放到这个目录下,通过那个配置项?
6.每个reducer的大小,默认是1G,输入文件如果是10G,那么就会起10个reducer;通过那个配置项可以配置?
7.group by操作是否允许数据倾斜,通过那个配置项配置?
8.本地模式时,map/reduce的内存使用量该如何配置?
9.在做表join时缓存在内存中的行数,默认25000;通过那个配置项可以修改?
10.是否开启数据倾斜的join优化,通过那个配置项可以优化?
11.并行运算开启时,允许多少作业同时计算,默认是8;该如何修改这个配置项?

hive 的调优及查询注意事项;
优化:
1、优化的方法:分区裁剪,列裁剪,行裁剪
2、少用distinct count
数据量小的时候无所谓,数据量大的情况下,由于COUNT DISTINCT操作需要用一个Reduce Task来完成,这一个Reduce需要处理的数据量太大,就会导致整个Job很难完成,一般COUNT DISTINCT使用先GROUP BY再COUNT的方式替换:
SELECT day,
COUNT(DISTINCT id) AS uv
FROM lxw1234
GROUP BY day
可以转换成:
SELECT day,
COUNT(id) AS uv
FROM (SELECT day,id FROM lxw1234 GROUP BY day,id) a
GROUP BY day;
虽然会多用一个Job来完成,但在数据量大的情况下,这个绝对是值得的。
(count distinct 在业务中好像无法避免,有优化方案,等找到了再补充)
3、开并行
4、避免数据倾斜
造成数据倾斜的原因有:1、数据本身 2、count distinct group by join 等操作造成
如何优化:
数据倾斜是Hive开发中对性能影响的一大杀手。
症状:
任务迚度长时间维持在99%(或100%);
查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成。
本地读写数据量很大。
导致数据倾斜的操作:
GROUP BY, COUNT DISTINCT, join
原因:
key分布不均匀
业务数据本身特点
这里列出一些常用的数据倾斜解决办法:
使用COUNT DISTINCT和GROUP BY造成的数据倾斜:
存在大量空值或NULL,或者某一个值的记录特别多,可以先把该值过滤掉,在最后单独处理:
SELECT CAST(COUNT(DISTINCT imei)+1 AS bigint)
FROM lxw1234 where pt = ‘2012-05-28′
AND imei <> ‘lxw1234′ ;
比如某一天的IMEI值为’lxw1234’的特别多,当我要统计总的IMEI数,可以先统计不为’lxw1234’的,之后再加1.
多重COUNT DISTINCT
通常使用UNION ALL + ROW_NUMBER() + SUM + GROUP BY来变通实现。
使用JOIN引起的数据倾斜
关联键存在大量空值或者某一特殊值,如”NULL”
空值单独处理,不参与关联;
空值或特殊值加随机数作为关联键;(做随机值去关联,效果最好)
不同数据类型的字段关联
转换为同一数据类型之后再做关联

查询注意点:
1、对同一张表的union all 要比多重insert快的多,
原因是hive本身对这种union all做过优化,即只扫描一次源表;
而多重insert也只扫描一次,但应为要insert到多个分区,所以做了很多其他的事情,导致消耗的时间非常长;

对于union all 不同的表
如果union all的部分个数大于2,或者每个union部分数据量大,应该拆成多个insert into 语句,实际测试过程中,执行时间能提升50%
insert overwite table tablename partition (dt= …)
select … from (
select … from A
union all
select … from B
union all
select … from C
) R
where …;
可以改写为:
insert into table tablename partition (dt= …)
select … from A
WHERE …;
insert into table tablename partition (dt= …)
select … from B
WHERE …;

2、过滤需要尽早过滤,不要都放在逻辑后的where中过滤
3、使用jion 和group 时需要注意
4、尽量不适用复杂的逻辑,可以使用中间表来规避
5、控制map和reduce的数量问题

解决数据倾斜的方法:
1.调节hive配置参数
设置hive.map.aggr = true map端部分聚合,相当于Combiner
设置hive.groupby.skewindata = true 有数据倾斜时,查询计划生成两个mr job, 第一个job先进行key随机分配处理,先缩小数据量。第二个job再进行真正的group by key处理。

2.SQL语句优化
大小表进行连接时,使用map join让小表先进内存,在map端完成reduce。
大表连接大表时,如果是空值造成数据倾斜,那么把空值变成一个字符串加上随机数,把这部分倾斜的数据分发到不同的reduce上。
如果count distinct有大量相同特殊值 (如空值) 空值可以不用处理,直接最后count结果加1即可。或者空值单独拿出来处理,最后再union回去。
不同数据类型关联 默认的hash操作会按其中一种类型的值进行分配,导致别一种类型全部分发到同一个reduce中。把两个关联的类型转换成相同类型。

一、控制Hive中Map和reduce的数量

Hive中的sql查询会生成执行计划,执行计划以MapReduce的方式执行,那么结合数据和集群的大小,map和reduce的数量就会影响到sql执行的效率。

除了要控制Hive生成的Job的数量,也要控制map和reduce的数量。

1、 map的数量,通常情况下和split的大小有关系,之前写的一篇blog“map和reduce的数量是如何定义的”有描述。

hive中默认的hive.input.format是org.apache.hadoop.hive.ql.io.CombineHiveInputFormat,对于combineHiveInputFormat,它的输入的map数量

由三个配置决定,

mapred.min.split.size.per.node, 一个节点上split的至少的大小

mapred.min.split.size.per.rack 一个交换机下split至少的大小

mapred.max.split.size 一个split最大的大小

它的主要思路是把输入目录下的大文件分成多个map的输入, 并合并小文件, 做为一个map的输入. 具体的原理是下述三步:

a、根据输入目录下的每个文件,如果其长度超过mapred.max.split.size,以block为单位分成多个split(一个split是一个map的输入),每个split的长度都大于mapred.max.split.size, 因为以block为单位, 因此也会大于blockSize, 此文件剩下的长度如果大于mapred.min.split.size.per.node, 则生成一个split, 否则先暂时保留.

b、现在剩下的都是一些长度效短的碎片,把每个rack下碎片合并, 只要长度超过mapred.max.split.size就合并成一个split, 最后如果剩下的碎片比mapred.min.split.size.per.rack大, 就合并成一个split, 否则暂时保留.

c、把不同rack下的碎片合并, 只要长度超过mapred.max.split.size就合并成一个split, 剩下的碎片无论长度, 合并成一个split.

举例: mapred.max.split.size=1000

mapred.min.split.size.per.node=300

mapred.min.split.size.per.rack=100

输入目录下五个文件,rack1下三个文件,长度为2050,1499,10, rack2下两个文件,长度为1010,80. 另外blockSize为500.

经过第一步, 生成五个split: 1000,1000,1000,499,1000. 剩下的碎片为rack1下:50,10; rack2下10:80

由于两个rack下的碎片和都不超过100, 所以经过第二步, split和碎片都没有变化.

第三步,合并四个碎片成一个split, 长度为150.

如果要减少map数量, 可以调大mapred.max.split.size, 否则调小即可.

其特点是: 一个块至多作为一个map的输入,一个文件可能有多个块,一个文件可能因为块多分给做为不同map的输入, 一个map可能处理多个块,可能处理多个文件。

2、 reduce数量

可以在hive运行sql的时,打印出来,如下:

Number of reduce tasks not specified. Estimated from input data size: 1
In order to change the average load for a reducer (in bytes):
set hive.exec.reducers.bytes.per.reducer=
In order to limit the maximum number of reducers:
set hive.exec.reducers.max=
In order to set a constant number of reducers:
set mapred.reduce.tasks=

reduce数量由以下三个参数决定,
mapred.reduce.tasks(强制指定reduce的任务数量)

hive.exec.reducers.bytes.per.reducer(每个reduce任务处理的数据量,默认为1000^3=1G)

hive.exec.reducers.max(每个任务最大的reduce数,默认为999)

计算reducer数的公式很简单N=min( hive.exec.reducers.max ,总输入数据量/ hive.exec.reducers.bytes.per.reducer )

只有一个reduce的场景:
a、没有group by 的汇总
b、order by
c、笛卡尔积

二、join和Group的优化
对于普通的join操作,会在map端根据key的hash值,shuffle到某一个reduce上去,在reduce端做join连接操作,内存中缓存join左边的表,遍历右边的表,一次做join操作。所以在做join操作时候,将数据量多的表放在join的右边。
当数据量比较大,并且key分布不均匀,大量的key都shuffle到一个reduce上了,就出现了数据的倾斜。

   对于Group操作,首先在map端聚合,最后在reduce端坐聚合,hive默认是这样的,以下是相关的参数
     · hive.map.aggr = true是否在 Map 端进行聚合,默认为 True
    · hive.groupby.mapaggr.checkinterval = 100000在 Map 端进行聚合操作的条目数目


   对于join和Group操作都可能会出现数据倾斜。
    以下有几种解决这个问题的常见思路
  1、参数hive.groupby.skewindata = true,解决数据倾斜的万能钥匙,查询计划会有两个 MR Job。第一个 MR Job 中,Map 的输出结果集合会随机分布到 Reduce 中,每个 Reduce 做部分聚合操作,并输出结果,这样处理的结果是相同的 Group By Key 有可能被分发到不同的 Reduce 中,从而达到负载均衡的目的;第二个 MR Job 再根据预处理的数据结果按照 Group By Key 分布到 Reduce 中(这个过程可以保证相同的 Group By Key 被分布到同一个 Reduce 中),最后完成最终的聚合操作。
  2、where的条件写在join里面,使得减少join的数量(经过map端过滤,只输出复合条件的)
  3、mapjoin方式,无reduce操作,在map端做join操作(map端cache小表的全部数据),这种方式下无法执行Full/RIGHT OUTER join操作
  4、对于count(distinct)操作,在map端以group by的字段和count的字段联合作为key,如果有大量相同的key,那么会存在数据倾斜的问题
  5、数据的倾斜还包括,大量的join连接key为空的情况,空的key都hash到一个reduce上去了,解决这个问题,最好把空的key和非空的key做区分
     空的key不做join操作。

当然有的hive操作,不存在数据倾斜的问题,比如数据聚合类的操作,像sum、count,因为已经在map端做了聚合操作了,到reduce端的数据相对少一些,所以不存在这个问题。

四、小文件的合并
大量的小文件导致文件数目过多,给HDFS带来压力,对hive处理的效率影响比较大,可以合并map和reduce产生的文件
· hive.merge.mapfiles = true是否和并 Map 输出文件,默认为 True
· hive.merge.mapredfiles = false是否合并 Reduce 输出文件,默认为 False
· hive.merge.size.per.task = 25610001000合并文件的大小

五、in/exists(not)
通过left semi join 实现 in操作,一个限制就是join右边的表只能出现在join条件中

六、分区裁剪
通过在条件中指定分区,来限制数据扫描的范围,可以极大提高查询的效率

七、排序
order by 排序,只存在一个reduce,这样效率比较低。
可以用sort by操作,通常结合distribute by使用做reduce分区键

你可能感兴趣的:(hive)