语句级别优化
--列、分区裁剪
查询过程中减少不必要的分区和列的查询。
--NULL处理
-如无需对应字段可以在语句中直接过滤;
-如需要可以提前筛选出来Union all关联输出,或者赋予新值(测试结果显示更优于前者)。
--不同类型字段关联
会导致按照数据类型分配Reducer,导致数据倾斜,此处需要转化为同一类型。
--Join操作
-大&小表:小表在左(会被先加载),大表在右。新版Hive已经处理了这个问题,会自动优化。
-大&大表:减少查询量,如仅查询增量
-map join:当一个表比较小时,可以开始此功能,将join从reducer提前到Map阶段。Join操作在Map阶段完成,不再需要Reduce,所以Map Task的个数就等于结果文件数。
//开启MapJoin功能
set hive.auto.convert.join = true;
--谓词下推
//默认开启
set hive.optimize.ppd = true;
-注意:如果使用外连接,则谓词下推会失效
--group by操作
默认情况下,完成Map阶段后,同一key值会发送到同一reducer,此时一个key值过大的就会产生数据倾斜。针对这种情况有一下两种方式:
方法一:Map阶段部分聚合
//开启Map聚合参数设置
set hive.map.aggr=true
//预先取N(此处设置为100000)条数据聚合
set hive.grouby.mapaggr.checkinterval=100000
//聚合后的条数/100000>0.5,则不再聚合
set hive.map.aggr.hash.min.reduction=0.5
方法二:参数控制负载均衡(生成两个MR任务,第一阶段完成预处理,同key可能发送到不同的reducer中,完成负载均衡;第二阶段完成最终的聚合结果)
//有数据倾斜的时候进行负载均衡
set hive.groupby.skewindata = true
--count&distinct操作
数据量大的情况下,count distinct需要一个reduce task完成,这一个reducer处理数据量太大。建议使用先group by再count的方式。
Map&Reduce级别优化
--减少Map数
主要针对小文件(远小于文件块大小)较多的情况,如一个SQL查询对应共有10000个文件,但其中很多是远小于128MB的小文件,总大小只有1G,正常执行会用10000个map任务,将会耗费大量的Map计算资源。那么此时需要通过合并文件的方式来减少map数,如下:
//执行前进行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
//mapred切分的大小,128MB
set mapred.max.split.size= 128000000;
//一个节点上split的至少的大小,数据在一个节点会合并,在多个不同的节点会把数据抓过来进行合并
set mapred.min.split.size.per.node= 100000000;
//一个交换机下split的至少的大小(这个值决定了多个交换机上的文件是否需要合并)
set mapred.min.split.size.per.rack= 128000000;
--增大Map数
当input的文件比较大且任务逻辑复杂,从而导致map执行非常慢,此时可以考虑增加Map数,使得每个map处理的数据量减少,从而提高任务的执行效率。
//会将一个文件表,随机的分散到10个文件表中,再用这10个表代替上面sql中的表,会用10个map任务去完成
set mapred.reduce.tasks=10;
--Reduce数确定与调整
在不指定reducer个书的情况下,hive会根据以下设定来确定个数
//每个reduce任务处理的数据量,默认为256M,在hive0.14.0之前默认是1G
hive.exec.reducers.bytes.per.reducer
//每个任务最大的reduce数,默认为1009,在hive0.14.0之前默认是999
hive.exec.reducers.max(每个任务最大的reduce数,默认为999)
以上,计算reducer数取其中最小值
--只有一个reducer的情况
当操作都是全局的,如没有group by的汇总、使用order by、存着笛卡尔乘积
文件级别优化
--源头减少
-使用distribute by分区,尽量少使用动态分区
-减少reduce的数据
--文件合并
-重建表,建表时减少reduce数量
-hadoop archive文件归档
-合并Map和Reduce的结果文件
//设置map端输出进行合并
set hive.merge.mapfiles = true
//设置reduce端输出进行合并
set hive.merge.mapredfiles = true
//设置合并文件的大小
set hive.merge.size.per.task = 256000000
//当平均输出的文件大小小于该值时,启动一个独立的MapReduce任务进行文件merge
set hive.merge.smallfiles.avgsize=16000000
系统级别优化
--计算引擎
当前可以使用的计算引擎有MR、TEZ、SPARK,可以通过hive.execution.engine设置
--存储格式
-TextFile:默认格式,行存储,数据不压缩;可以使用压缩算法,但是压缩后不切分。
-SequenceFile:二进制文件,行存储,Hadoop API提供的一种二进制文件,以key-value的形式序列化到文件中。支持三种级别压缩,block级别最好。
-RCFile:数据按行分块,每块按列存储,不支持任意方式的数据写操作,仅提供一种追加接口。
-ORCFile:是RCFile的改良版本
其中SequenceFile、RCFile、ORC格式的表不能直接从本地文件导入数据,数据要先导入到TextFile格式的表中,然后再从TextFile表中用insert导入到SequenceFile、RCFile表中。另外还有Parquet、AVRO等格式
--本地MR
如果在hive中运行的sql本身数据量很小,那么使用本地MR的效率要比分布式的快很多。如下三个参数都满足时,才会使用本地MR:
//开启本地MR,默认关闭
set hive.exec.mode.local.auto=true;
//设置Local MR的最大输入数据量,当输入数据量小于时采用Local MR的方式
set hive.exec.mode.local.auto.inputbytes.max=134217728;
//设置Local MR的最大输入文件个数,当输入文件个数小于时采用Local MR的方式
set hive.exec.mode.local.auto.input.files.max=4;
--并行执行
应用于可以并行运行的MR作业,例如在联接之前处理不同源表的作业。从Hive0.14开始,也适用于移动可以并行运行的任务,例如在多次插入期间移动文件以插入目标。通过set hive.exec.parallel=true设置。