Hive调优

138 阅读6分钟

设置Hive参数

作用域:set参数设置<启动服务命令行<修改配置文件
优先级:set参数设置>启动服务命令行>修改配置文件(就近原则)
注意:Hive配置文件优先级>Hadoop配置文件优先级

调优

设置数据压缩格式

一般使用snappy,压缩速率250M/s,解压速度500m/s
核心:可以设置map端压缩,减少map到reduce的数据传输量,提升效率

设置数据存储格式

存储格式的经典代表 ORC列式存储,默认压缩格式为zlib,但一般搭配snappy使用
核心:建表的时候使用stored as 存储方式来限定数据的存储方式以及对应的压缩方案

行存储和列存储的优缺点:
    行存储:
        优点:查询一整条数据时很方便,只需找到其中一个数据,其余数据就在附近.
        缺点:在查询一整个字段的数据时需要一行一行的扫描,效率不高,存储数据时相邻数据的类型不一致,造成空间资源浪费
        代表:textfile和squencefile''
   列存储:
        优点:查询一整个字段数据时很方便,相邻数据类型一致,提高资源利用率
        缺点:查询一整行数据时不方便
        代表:orc和parquet

fetch抓取

核心:能不走MR就不走MR
3.X版本默认开启调优(more模式)
三种模式:more (默认值): 可以保证在执行全表扫描, 查询某几个列, 进度limit操作,还有简单条件查询4种情况都不会走MR
        minimal:保证执行全表扫描以,查询某几个列,简单limit操作,3种情况可以不走MR
        none:全部的查询的SQL 都执行MR     

join优化

核心1:map端提前join,减少reduce工作量
核心2:数据能提前过滤就提前过滤,减少join数据量
    三种形式:
            小表join大表:set hive.auto.convert.join = true; -- 默认为true  开启mapJoin支持 
                        set hive.mapjoin.smalltable.filesize= 25000000;  设置 小表的最大的数据量  23.84m
            中表join大表:核心为能提前过滤就提前过滤,减少join次数
                        中表过滤后可能会变成小表,也就意味着可能符合map端join的条件
            大表join大表:核心为能提前过滤就提前过滤,减少join次数
            

本地模式

核心:MR能走本地模式就走本地模式,小任务自己干
如何开启:
	set hive.exec.mode.local.auto=true;  默认值为: false
开启本地模式后, 在什么情况下执行本地MR:   只有当输入的数据满足以下两个特性后, 才会执行本地MR
	set hive.exec.mode.local.auto.inputbytes.max=51234560;   默认为 128M 
		设置本地MR最大处理的数据量
	set hive.exec.mode.local.auto.input.files.max=10; 默认值为4
		设置本地MR最大处理的文件的数量

SQL优化

列裁剪:默认开启,只读取SQL需要的字段,减少读取开销,提升效率

分区裁剪:默认开启,如果操作的表是一张分区表, 那么建议一定要带上分区字段, 以减少扫描的数据量, 从而提升效率
        执行查询SQL的时候, 能在join之前提前进行条件过滤的操作, 一定要提前过滤, 不要在join后进行过滤操作
        
负载均衡:有数据倾斜的时候进行负载均衡(默认是falseset hive.groupby.skewindata = true;

count(distinct):核心: 大任务的时候count(distinct)默认一个mr程序,会非常慢,核心就是拆分成两个任务去执行(先group by分组再count统计)
                注意: 如果是小任务,拆分两个mr反而效率低,以后大表的时候才会真正提升效率
               
优化笛卡尔积:尽量避免出现笛卡尔积
            注意事项:1) 避免join的时候不加on条件,或者无效的on条件
                    2) 关联条件不要放置在where语句, 因为底层, 先产生笛卡尔积 然后基于where进行过滤 , 建议放置on条件上
                    3) 如果实际开发中无法确定表与表关联条件 建议与数据管理者重新对接, 避免出现问题

Hive动态分区

核心:动态生成分区目录 先复制表结构(like)在插入数据
两种方式:
        不关闭严格模式下动态分区:insert into table 新分区表  select * from 原分区表 ;
        关闭严格模式: set hive.exec.dynamic.partition.mode=nonstrict;
        关闭严格模式下动态分区:insert into table 新分区表 partition(分区字段名) select * from 原分区表 ;

map和reduce数量

核心问题:
1>是不是map数越多越好?
答案是否定的。如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,
而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。

2>是不是保证每个map处理接近128m的文件块,就高枕无忧了?
答案也是不一定。比如有一个127m的文件,正常会用一个map去完成,但这个文件只有一个或者两个小字段,却有几千万的记录,
如果map处理的逻辑比较复杂,用一个map任务去做,肯定也比较耗时。

3>是不是reduce数越多越好?
答案是否定的。如果reduce设置的过大,对整个作业会产生一定的影响。
过多的启动和初始化reduce也会消耗时间和资源;
另外,有多少个reduce,就会有多少个输出文件,如果生成了很多个小文件,那么如果这些小文件作为下一个任务的输入,
则也会出现小文件过多的问题;

4>在什么情况下, 只能有一个reduce呢?
以下几种, 不管如何设置, 最终翻译后reduce只能有一个
    1) 执行order by操作 
    2) 执行不需要group by直接聚合的操作
    3) 执行笛卡尔积

并行执行

核心:  sql语句底层多个阶段如果互不依赖,可以设置并行执行提升效率
set hive.exec.parallel=false;              --打开任务并行执行,默认关闭
set hive.exec.parallel.thread.number=8;  --同一个sql允许最大并行度,默认为8。

严格模式

核心:  效率低下的sql尽量不要编写执行
set hive.mapred.mode = strict;  --开启严格模式   
set hive.mapred.mode = nonstrict; --开启非严格模式  最新版本默认

jvm重用

核心:  资源重复使用
注意: 默认情况下, container资源容器  只能使用一次,不能重复使用, 开启JVM重用, 运行container容器可以被重复使用,
      在hive2.x已经默认支持了

推测执行

核心:  提前推测出拖后腿任务,为它开启一个备份任务,最终以先执行完的结果为准
set hive.mapred.reduce.tasks.speculative.execution=true;默认开启

查看explain执行计划

核心:  帮助咱们查看sql底层执行信息,了解底层,帮助更好调优操作
语句:explain SQL语句;