Hive优化

1.基础优化

1.1 hive并行操作

  • Hive编译查询限制 : (一般是作为通用配置: cm的hive上面)
    • 说明: Hive默认同时只能编译一段HiveQL,并上锁
	如何解决多个会话时, 同时只能有一个会话进行编译的问题 ? 
	hive.driver.parallel.compilation 设置为true  是否开启一次性编译多个sql的功能 默认为 false
	hive.driver.parallel.compilation.global.limit  默认值为3 表示一次性最多同时有三个会话进行编译sql
	注意: 如果此值设置为 0 表示无边界, 此值是否会生效取决于第一个参数是否设置为true
  • Hive不同阶段任务并行执行 : (一般是进行单独会话配置)
    • 说明: Hive会将一个查询转化为一个或多个阶段,包括:MapReduce阶段、抽样阶段、合并阶段、limit阶段等。默认情况下,一次只执行一个阶段。不过,如果某些阶段不是互相依赖,是可以并行执行的。
set hive.exec.parallel=true;   默认值为false  表示是否要开启hive的并行执行
set hive.exec.parallel.thread.number=16; 表示一次性一个sql中最大运行并行的数量  默认值8

1.2 hive的小文件合并

  • hive在执行的sql的时候, 会将sql翻译为MR来执行, MR的读取目标数据的时候, 如果目标数据中有大量的小文件, 此时就会导致启动多个mapTask来执行, 此时对系统资源是一种极大的浪费, 导致执行效率降低
  • reduce小文件过多会有什么影响?
    1.对HDFS不友好
    2 下次对结果表进行操作, 又会小文件过多的问题
  • 解决方案: 在读取数据的时候, 对目标数据进行小文件合并, 将其合并为一个较大的文件 从而减少mapTask的数量
hive.merge.mapfiles : 是否开启 map端的小文件合并的操作:  默认值为 true
hive.merge.mapredfiles:  是否要开启reduce的输出小文件合并 : 默认值为false
hive.merge.size.per.task: 表示合并后的文件的大小 默认值为 268435456(256M) 
hive.merge.smallfiles.avgsize: 表示当输出文件的平均大小小于此设置值时,启动一个独立的map-reduce任务进行文件merge,默认值为16M。

注意: 以上调整的参数, 均可以直接在CM上调整操作

1.3 hive的矢量化查询

  • hive的默认查询执行引擎一次处理一行,而矢量化查询执行是一种hive特性,目的是按照每批1024行读取数据,并且一次性对整个记录整合(而不是对单条记录)应用操作,也可以理解为批量化操作
set hive.vectorized.execution.enabled=true; 默认就是true   是否开启批量化查询

注意事项:要求读取的表的数据格式为ORC

1.4 读取零拷贝

  • 在读取HDFS的数据的时候, 只需要将需要的数据读取到内存中, 不需要的数据, 就不进行读取操作
  • 注意事项: 如果想要实现此功能, 要求表的数据格式 ORC
set hive.exec.orc.zerocopy=true;   默认值为false
示例: 
	A 表中 b c d 三个字段
	执行以下操作:
		select  b,c from A where  b= '' ;  在开启读取零拷贝的情况下, 读取数据的时候, 只需要将表中 b和c这两列的数据读取到内存中即可
  • 总结
set hive.driver.parallel.compilation=true
set hive.driver.parallel.compilation.global.limit=3
set hive.exec.parallel=true;
set hive.exec.parallel.thread.number=16; 
set hive.exec.orc.zerocopy=true; 

2.数据倾斜优化

2.1 数据倾斜的原因和导致数据倾斜的操作

  • 出现数据倾斜原因:map输出数据按key Hash的分配到reduce中,由于key分布不均匀、业务数据本身的特性、建表时考虑不周、等原因造成的reduce 上的数据量差异过大。
    • key分布不均匀;
    • 业务数据本身的特性;
    • 建表时考虑不周
    • 某些SQL本身导致的数据倾斜
  • 在进行join、group by操作的时候会导致数据倾斜

2.2 解决数据倾斜的方案

2.2.1 解决数据倾斜-join倾斜
  • 解决方案一:通过mapjoin bucket mapjoin和smb join解决
    • 小表和大表join,使用map join
    • map join 不局限于任何类型表
map join原理:运行时直接将小表加载到内存中,在map端完成join操作
缺点:加大内存占用,如果内存不足,容易造成内存泄漏,只适用于小表和大表关联

开启map join方法:
set hive.auto.convert.join=true;  -- 是否开启 map join 工作
set hive.auto.convert.join.noconditionaltask.size=512000000;  -- 设置小表临界值大小 默认值: 20M
  • 中型表和大表关联,使用bucket mapjoin
使用要求:
	1)必须开启bucket map join支持:  set hive.optimize.bucketmapjoin = true;
	2)一个表的bucket数是另一个表bucket数的整数倍
	3)bucket列 == join4)必须是应用在map join的场景中
	5) 表必须是分桶表
  • 大型表和大型表关联,使用smb(Sort merge Bucket) mapjoin
满足条件:
	1)必须开启bucket map join支持:  set hive.optimize.bucketmapjoin = true;
	2)一个表的bucket数等于另一个表bucket数
	3)bucket列 == join== sort列
	4)必须是应用在bucket map join的场景中
	5) 表必须是分桶表

-- 启动桶表  
set hive.enforce.bucketing=true;  
-- 保证必须进行强制排序操作
set hive.enforce.sorting=true;
-- 开启 bucket map join
set hive.optimize.bucketmapjoin = true;
-- 开启 SMB join
set hive.auto.convert.sortmerge.join=true;
set hive.auto.convert.sortmerge.join.noconditionaltask=true;
-- 是否自动尝试使用SMB join 连接   可以直接在CM中配置
set hive.optimize.bucketmapjoin.sortedmerge = true;


如何保证, 分桶表中,按照分桶字段进行排序呢?
第一步: 建表的时候
create table test_smb_2(mid string,age_id string)
CLUSTERED BY(mid) SORTED BY(mid) INTO 500 BUCKETS;

第二步: --写入数据强制排序
set hive.enforce.sorting=true;
  • 解决方案二:将那些容易产生数据倾斜的key值抽取出来, 使用一个单独的MR进行处理即可
    • 实施方案一: 运行时优化
    • 说明:
      在运行的过程中, 时刻监控着k2的值, 当k2中某个值出现的次数大于设置的值, 认为此值出现数据倾斜, 将其单独存储起来, 通过一个单独的MR对其进行单独处理即可
    • 注意: 此种优化, 如果数据中 大多数key都大于了此值, 如果要使用这个优化, 需要调整hive.skewjoin.key此值大小
    • 配置:
set hive.optimize.skewjoin=true; 开启 运行时的join数据倾斜优化
set hive.skewjoin.key=100000; 当这个key的值出现多少个的时候, 认为是有数据倾斜的问题	
  • 实施方案二: 编译时优化
    • 整体优化思想都是一样的, 只不过编译时优化在编译器形成执行计划的时候, 就已经优化完毕了
    • 注意: 在执行之前,或者建表之前, 就需要指定那些key的值会导致数据倾斜
    • 配置:
set hive.optimize.skewjoin.compiletime=true;  默认关闭  

--建表示例:
	CREATE TABLE list_bucket_single (key STRING, value STRING)
	-- 倾斜的字段和需要拆分的key值
	SKEWED BY (key) ON (1,5,6)
	--  为倾斜值创建子目录单独存放
	[STORED AS DIRECTORIES];

在具体使用时候, 可以两个都开启为true, 这样当出现了编译期设置的key值, 直接就进行优化了, 如果是编译期没有考虑到的值, 在运行过程中, 发现了, 也可以进行优化处理

2.2.2 union all的优化
  • 在进行join的数据倾斜优化的时候, 不管采用 运行时的, 还是编译时, 都是将能产生倾斜的key值, 单独拿出来, 使用一个单独MR进行处理, 处理后和之前结果进行union all 合并操作
  • 正常情况下, union all 也需要单独运行一个MR, 将两个结果进行合并, 出现到一个目标目录下,而再增加一个MR,也会对效率产生影响
  • 解决方案:不执行union all,直接让新产生的MR的结果输出到目的地
  • 配置:
set hive.optimize.union.remove=true;
2.2.3 解决数据倾斜-group by倾斜
  • 方案一:小规约 开启 map端的局部聚合操作
    • 配置: hive.map.aggr=true;
  • 方案二: 大规约 运行两个MR , 第一个MR 进行局部聚合操作, 第二个MR 进行最终聚合操作
    • 配置:hive.groupby.skewindata=true;
    • 注意事项:
如果使用方案二进行group by 数据倾斜的解决, 要求sql中不允许出现多次distinct操作, 只能出现一次
例如: 
	SELECT ip, count(DISTINCT uid), count(DISTINCT uname) FROMlog GROUP BY ip 
		此操作 就会直接报错, 因为此sql中出现多次distinct操作
		报错内容: DISTINCT on different columns notsupported with skew in data.

3 关联优化器

  • 在hive执行sql的时候, 一个sql翻译的MR中可能会出现多次shuffle操作, 而多次的shuffle操作有可能是可以共享的, 此时就可以将shuffle进行共享, 从而减少shuffle次数, 从而提升效率
  • 配置:set hive.optimize.correlation=true;

总结

set hive.driver.parallel.compilation=true
set hive.driver.parallel.compilation.global.limit=3
set hive.exec.parallel=true;
set hive.exec.parallel.thread.number=16;    -- 以上四个是hive的并行优化
set hive.merge.mapfiles = true ;  -- 开启hive的map端小文件合并
set hive.merge.mapredfiles= true; -- 开启hive的reduce端小文件合并
set hive.exec.orc.zerocopy=true;   -- hive的读取零拷贝
set hive.vectorized.execution.enabled=true; -- hive的矢量化的查询优化

set hive.optimize.correlation=true; -- hive的关联优化器
set hive.optimize.skewjoin=true;
set hive.optimize.skewjoin.compiletime=true;  -- hive的 join的数据倾斜的优化
set hive.optimize.union.remove=true;  -- hive union all的优化方案
set hive.map.aggr=true;   
set hive.groupby.skewindata=true;   -- hive的 group by 数据倾斜的优化
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值