Hive的相关优化

1、hive的相关优化

1.1 hive的压缩配置

压缩有什么用?

'好处':
	在有限的空间下,存储更多的资源
'坏处':
	压缩和解压需要消耗额外的资源	
  • 通过压缩 优化MR 提升效率
位置一: 'map阶段的输出结果上'
	'好处一':当reduce在拉取数据的时候,由于数据已经压缩,所以整个数据量减少,从而减少网络带宽,提升拉取的效率
	'好处二':在一些特殊情况下,整个MR只有map 没有reduce的,此时map输出的结果就是最终的结果,对结果进行压缩,减少磁盘存储,提升磁盘利用率

位置二:'reduce阶段到的输出结果上'
	reduce的输出就是最终的输出, 会落在HDFS上形成最终的文件, 
	此文件进行压缩, 减少磁盘存储, 提升磁盘的利用率
  • 使用那种数据压缩呢?
选择压缩方案的时候 需要看什么指标呢?  压缩比 和 解压缩的性能

说明:  
	'压缩比: zlib 和 gz'
	'解压缩性能: LZO  snappy'
	
	'性价比:  snappy'

总结: 
	当对数据'写入多, 读取少'的情况下, 建议优先考虑压缩比 : zlib (ODS层)
	当对数据'读取比较多'的情况下, 建议优先考虑解压缩的性能: snappy (其他层次结构)
	
	如果生产环境中, 公司服务器的磁盘空间比较宽裕的, 建议不管在什么位置上, 都使用snappy压缩方案
  • hadoop提供的压缩方案
    hadoop提供的压缩方案

     注意事项:
     	对于snappy的压缩方案, 默认的apache版本的hadoop是不支持的, 如果想使用需要对hadoop进行重新编译才可以
     	而一些商业环境的hadoop版本基本都是直接支持snappy压缩方案: 比如 CDH版本
    
  • 压缩方案的配置

map阶段的压缩配置:
1)开启hive中间传输数据压缩功能
set hive.exec.compress.intermediate=true;
2)开启mapreduce中map输出压缩功能
set mapreduce.map.output.compress=true;
3)设置mapreduce中map输出数据的压缩方式
set mapreduce.map.output.compress.codec= org.apache.hadoop.io.compress.SnappyCodec;


reduce阶段的压缩配置:
1)开启hive最终输出数据压缩功能
set hive.exec.compress.output=true;
2)开启mapreduce最终输出数据压缩
set mapreduce.output.fileoutputformat.compress=true;
3)设置mapreduce最终数据输出压缩方式
set mapreduce.output.fileoutputformat.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;

4)设置mapreduce最终数据输出压缩为块压缩
set mapreduce.output.fileoutputformat.compress.type=BLOCK;

1.2 hive的数据存储格式

hive支持的存储数据的格式主要有:textfile(行式存储),sequencefile(行式存储)、ORC(列式存储)、
parquet(列式存储)
  • 什么是行式存储 , 什么是列式存储呢? 以及各有什么优缺点呢?
    存储说明

ORC:

	1)将数据先按照进行分隔为多个script片段
	2)在每一个片段中按照列式存储数据
	3)在每一个script片段中都是有索引信息的

通过实验比对:
	ORC格式不管在存储上还是查询上, 都是非常优秀的
  • 常用的建表格式: 特别关注
create table log_orc_snappy(
    track_time string,
    url string,
    session_id string,
    referer string,
    ip string,
    end_user_id string,
    city_id string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
-- 关注以下这二行: 存储格式为ORC 同时数据压缩方案为SNAPPY
STORED AS orc tblproperties ("orc.compress"="SNAPPY"); --常用于其他层次表
或者:
STORED AS orc|textFile tblproperties ("orc.compress"="GZ|ZLIB"); --常用于ODS层表

注意事项:
	只有textFile支持通过load data 方式来加载数据, 其余数据结构,
	都需要通过insert + select方式插入数据

1.3 hive的其他优化

1.3.1 hive的fetch本地抓取

fetch本地抓取:在运行SQL的时候,能不走MR尽量不走MR 直接从HDFS上读取数据即可
  • 在那些情况下可以不走MR呢?
在hive中,主要可以通过一个配置,来开启fetch本地抓取:
	hive.fetch.task.conversion
		可选值:
			more (默认值)
			minimal
			none
more: 当值为more的时候, hive会在以下这几种情况不会走MR
	情况一: 查询全部数据  select * from表
	情况二: 查询某几个字段的时候  select 字段... from 表
	情况三: 执行简单的过滤操作的时候:  select 字段... fromwhere 字段='值'
	情况四: 执行limit的时候, 也不走MR查找: select * fromlimit 10

minimal: 当值为minimal的时候 ,hive会在以下这几种情况不会走MR
	情况一: 查询全部数据  select * from表
	情况二: 查询某几个字段的时候  select 字段... from 表
	情况三: 执行limit的时候, 也不走MR查找: select * fromlimit 10
	
none: 当值为none的时候 , hive会将全部的查询SQL走MR


生产环境中, 一般选择为 more ,而more正好默认值, 所以 不需要设置

1.3.2 hive的本地模式

hive的本地模式: 在执行MR的时候, 尽量以本地模式运行方案, 而不是提交到yarn集群
相关hive的配置:
	set hive.exec.mode.local.auto=true; 开启hive的本地模式 默认为 false
满足本地运行的条件: 当以下两个条件都满足的时候, 才可以走本地模式
	数据大小: set hive.exec.mode.local.auto.inputbytes.max=134217728; 默认为128M
	文件数量: set hive.exec.mode.local.auto.tasks.max=4 ; 默认为 4

生产环境配置:
	建议直接开启本地默认, 因为hive自动识别是否可以走本地
	
在实际使用, 这个操作, 只能在测试环境中有效, 在生产数据上配置, 其实意义不大, 因为生产数据远远超过这个值

1.3.3 join 查询优化

默认情况下 翻译后MR 是如何实现join连接的操作呢?
流程图

存在问题:       
		1) 可能出现数据倾斜的问题       
		2) reduce压力较大

如何解决问题?

  • 解决方案: map join
    map join
适合于 小表 join 大表的情况

map join相关的参数配置:
	set hive.auto.convert.join = true; -- 是否开启map join 默认为true
	set hive.mapjoin.smalltable.filesize= 25000000; -- 大小表的阈值
  • 中型表和大表的join:

    • 方案一:如果可以提前过滤的 建议在join之前过滤掉 以减少join的条数
    • 方案二: 如果表中有关键条件的字段上有大量的null 建议将null值替换为随机数
    • 方案三: 在分桶表中实施map join(bucket map join)
  • 大表和大表join:

    • 方案一:如果可以提前过滤的 建议在join之前过滤掉 以减少join的条数
    • 方案二:如果表中有关键条件的字段上有大量的null 建议将null值替换为随机数
    • 方案三: 在分桶表中实施map join(SMB map join)
  •  请注意: 目前 大表和小表进行join的时候, 没有了先后之分了, 无所谓, 
     		但是老版本中, 建议将小表放置在前面, 大表放置后面
    

1.3.4 group by的优化

group by 的数据倾斜的解决方案:

  • 方案一: 通过 combiner(规约) 解决
假设有如下这么一份数据:
s01  张三  大数据一班
s02  李四  大数据一班
s03  王五  大数据二班
s04  赵六  大数据一班
s05  田七  大数据二班
s06  周八  大数据一班
s07  李九  大数据一班

需求: 求每个班级有多少个人?
	select 班级名称,count(1) as num   from  stu group by  班级;


map阶段: 假设map 有二个

map1Task:
	k2        v2
  大数据一班   {s01,张三,大数据一班}
  大数据一班   {s02,李四,大数据一班}
  大数据二班   {s03,王五,大数据二班} 
  大数据一班   {s04,赵六,大数据一班}
map2Task:
    k2        v2
  大数据二班   {s05,田七,大数据二班}  
  大数据一班   {s06,周八,大数据一班}
  大数据一班   {s07,李九,大数据一班}


reduce阶段:   假设reduce 有二个



reduce1Task: 接收  大数据一班
接收到数据:
       k2           v2
	大数据一班   {s01,张三,大数据一班}
    大数据一班   {s02,李四,大数据一班}
	大数据一班   {s04,赵六,大数据一班}
	大数据一班   {s06,周八,大数据一班}
    大数据一班   {s07,李九,大数据一班}
分组操作:
	大数据一班  [{s01,张三,大数据一班},{s02,李四,大数据一班},{s04,赵六,大数据一班},{s06,周八,大数据一班},{s07,李九,大数据一班}]

reduce输出  
       k3       v3
     大数据一班   5

reduce2Task : 接收 大数据二班
接收到数据:
	   k2           v2
	  大数据二班   {s03,王五,大数据二班} 
      大数据二班   {s05,田七,大数据二班}  

分组操作:
	大数据二班  [{s03,王五,大数据二班},{s05,田七,大数据二班} ]

reduce输出  
       k3       v3
     大数据二班   2
     
发现 两个reduce之间存在数据倾斜的问题

解决方案一: combiner

假设有如下这么一份数据:
s01  张三  大数据一班
s02  李四  大数据一班
s03  王五  大数据二班
s04  赵六  大数据一班
s05  田七  大数据二班
s06  周八  大数据一班
s07  李九  大数据一班

需求: 求每个班级有多少个人?
	select 班级名称,count(1) as num   from  stu group by  班级;


map阶段: 假设map 有二个

map1Task:
	k2        v2
  大数据一班   {s01,张三,大数据一班}
  大数据一班   {s02,李四,大数据一班}
  大数据二班   {s03,王五,大数据二班} 
  大数据一班   {s04,赵六,大数据一班}

combiner(规约): 提前聚合操作 (将reduce的逻辑提前在每一个map中先做一遍)
输出结果:
   k2         v2
  大数据一班    3 
  大数据二班    1
  
map2Task:
    k2        v2
  大数据二班   {s05,田七,大数据二班}  
  大数据一班   {s06,周八,大数据一班}
  大数据一班   {s07,李九,大数据一班}
combiner(规约): 提前聚合操作(将reduce的逻辑提前在每一个map中先做一遍)
输出结果:
    k2        v2
  大数据一班    2
  大数据二班    1

reduce阶段:  二个reduce

reduce1Task : 接收大数据一班
接收到数据:
    大数据一班    3 
    大数据一班    2
分组操作:
     大数据一班   [3,2]
reduce输出:
     k3         v3
    大数据一班    5

reduce2Task: 接收大数据二班
    大数据二班    1
    大数据二班    1
分组操作:
	大数据二班   [1,1]

reduce输出:
      k3        v3
     大数据二班   2
     
 是否解决了倾斜: 解决了
  • 解决方案二: 大combiner (官方: 负载均衡)
方案: 利用多个MR实现, 第一个MR 将所有的数据均衡分给不同reduce, 有各个reduce计算出一个局部的结果, 这个过程就是负载均衡过程 (提前聚合操作)
第二个MR: 按照相同key发往同一个reduce, 实现最终聚合操作

案例流程: 
假设有如下这么一份数据:
s01  张三  大数据一班
s02  李四  大数据一班
s03  王五  大数据二班
s04  赵六  大数据一班
s05  田七  大数据二班
s06  周八  大数据一班
s07  李九  大数据一班

需求: 求每个班级有多少个人?
	select 班级名称,count(1) as num   from  stu group by  班级;


第一个MR:  
map1Task:
	k2        v2
  大数据一班   {s01,张三,大数据一班}
  大数据一班   {s02,李四,大数据一班}
  大数据二班   {s03,王五,大数据二班} 
  大数据一班   {s04,赵六,大数据一班}
map2Task:
    k2        v2
  大数据二班   {s05,田七,大数据二班}  
  大数据一班   {s06,周八,大数据一班}
  大数据一班   {s07,李九,大数据一班}
 
 特殊点: 让数据进行随机发放, 让每一个reduce都拿到相同个数的数据  (负载均衡)
  
reduce接收数据: 

reduce1Task:
接收到:
   大数据一班   {s01,张三,大数据一班}
   大数据二班   {s03,王五,大数据二班} 
   大数据一班   {s06,周八,大数据一班}
   大数据一班   {s07,李九,大数据一班}
输出结果:
    大数据一班     3
    大数据二班     1
reduce2Task:
接收到:
   大数据一班   {s02,李四,大数据一班}
   大数据一班   {s04,赵六,大数据一班}
   大数据二班   {s05,田七,大数据二班}  
 
输出结果:
	大数据一班    2
	大数据二班    1

第二个MR: 按照相同key发往同一个reduce

map阶段:
	大数据一班     3
    大数据二班     1
    大数据一班    2
	大数据二班    1

reduce:

reduce1Task: 大数据一班
接收:
   大数据一班     3
   大数据一班     2
结果:
	大数据一班    5

reduce2Task: 大数据二班
接收:
	大数据二班     1
	大数据二班     1
结果:
	大数据二班  2

总结: 第二种方案, 可以比第一种解决倾斜的问题更加良好
相关的配置:

方案一配置信息:
	set hive.map.aggr = true;  -- 开启 map端提前聚合(combiner)
	set hive.groupby.mapaggr.checkinterval = 100000;  -- 每一个map能够聚合最大条目

方案二配置信息:
	set hive.groupby.skewindata = true;  

1.3.5 MR的并行度设置

指的: 如何调整mapTask的数量 以及reduceTask的数量
  • mapTask的数量调整:
mapTask的数量是由什么来决定的呢?  文件的切片决定, 切片的大小默认与blcok大小是一致的
	意味着无法直接条件map的数量, '调整map数量需要从文件的切片上'

'比如想mapTask数量变得多一些: 设置切片的大小 小一些 或者输入的文件数量变得多一些'
'比如想mapTask数量变的少一些: 设置切片的大小 大一些 或者输入的文件数量变得少一些'

在hive中, 主要是以调整文件数量为主
  • reduceTask的数量调整:
在hive中 reduce的数量默认为 -1 , 由 hive基于数据量来自动调整的

调整方案:
	hive.exec.reducers.bytes.per.reducer=256123456; -- 每一个reduce默认处理数据量
	hive.exec.reducers.max=1009 ; -- 一个MR中最多可以运行多少个reduce
	mapreduce.job.reduces=-1;  -- 手动设置reduce的数量, 默认 -1 自动推断
	
在设置reduce个数的时候也需要考虑这两个原则:
	'处理大数据量利用合适的reduce数;使单个reduce任务处理数据量大小要合适;'

1.3.6 explain 查看执行计划

explain 关键词主要作用 查看当前SQL的执行计划,根据执行计划, 调整一些相关优化措施

语法格式:
		explain SQL语句;

1.3.7 并行执行机制

	在执行SQL的时候, SQL的执行可能会出现多个阶段, 各个阶段之间有可能出现没有任何的依赖, 
	此时安排这些阶段并行执行, 从而提升效率

相关配置:

set hive.exec.parallel=true; 是否开启并行执行
set hive.exec.parallel.thread.number=16; 最大允许的并行的数量

提前: 要想并行执行, 必须先的有资源, 如果没有资源, 即使可以并行 那也是无法并发的

1.3.7 严格模式

在hive中, 为了防止一些性能极差的SQL的执行, 专门提供严格模式进行限制
1) 对于分区表,除非where语句中含有分区字段过滤条件来限制范围,否则不允许执行
2) 对于使用了order by语句的查询,要求必须使用limit语句
3) 限制笛卡尔积的查询

1.3.8 推测执行 一般关闭,不使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值