转载请注明出处:https://blog.csdn.net/l1028386804/article/details/88430447

使用explain
在查询语句前加上explain关键字,然后来查询下查询计划和其他一些信息。这个查询本身是不会执行的。

hive> explain select sum(number) form onecol;

explain extended
使用explain extended可以产生更多的输出信息。

限制调整
在很多情况下limit语句还是需要执行整个查询语句,然后再返回部分结果。这种情况通常是浪费的,所以应该尽可能的避免出现这种情况。Hive有一个配置属性可以开启,当使用limit语句时,可以对源数据进行抽样:

<property>
	<name>hive.limit.optimize.enable</name>
	<value>true</value>
</property>

一旦属性hive.limit.optimize.enable的值设置为true,那么还会有两个参数可以控制这个操作,也就是hive.limit.row.max.size和hive.limit.optimize.limit.file

<property>
	<name>hive.limit.row.max.size</name>
	<value>100000</value>
</property>

<property>
	<name>hive.limit.optimize.limit.file</name>
	<value>10</value>
</property>

这个功能的缺点是,可能输入中游泳的数据永远不会被处理到。

join优化
要清楚哪个表是最大的,并将最大的表放置在join语句的最右边,或者直接使用/*streamtable(table_name)*/语句指出。
如果所有表中有一个表足够的小,是可以完全载入到内存中的,那么这时Hive可以执行一个map-side join,这样可以减少reduce过程,有时甚至可以减少某些map task任务。有时候即使某些表不适合载入内存也可以使用mapjoin,因为减少reduce阶段可能比将不太大的表分发到每个map task中会带来更多的好处。

本地模式
可以在执行过程中,临时启用本地模式:

hive> set oldjobtracker=${hiveconf:mapred.job.tracker};
hive> set mapred.job.tracker=local;
hive> set mapred.tmp.dir=/home/edward/tmp;
hive> select * from people where firstname=bob;
...
hive> set mapred.job.tracker=${oldjobtracker};

可以通过设置属性hive.exec.mode.local.auto的值为true,来让Hive在适当的时候自动启动这个优化。通常用户可以将这个配置卸载$HOME/.hiverc文件中。
如果希望对所有的用户都使用这个配置,那么可以将这个配置增加到$HOME/conf/hive-site.xml文件中:

<property>
	<name>hive.exec.mode.local.auto</name>
	<value>true</value>
</property>

并行执行
通过设置参数hive.exec.parallel值为true,开启并发执行,在集群共享中,如果job中并行执行的阶段增多,那么集群利用率就会增加:

<property>
	<name>hive.exec.parallel/name>
	<value>true</value>
</property>

严格模式
通过设置属性hive.mapred.mode的值为strict可以禁止3中类型的查询:
1) 对于分区表,除非where语句中含有分区字段过滤条件来限制数据范围,否则不允许执行
2) 对于使用order by语句的查询,要求必须使用limit语句。
3) 限制笛卡尔积的查询


调整Mapper和Reducer个数
Hive是按照输入的数据量大小来确定reducer个数的。我们可以通过dfs -count命令来计算输入量的大小,这个命令和Linux中的du -s命令类似;可以计算指定目录下所有数据的总大小:
属性hive.exec.reducers.bytes.per.reducer默认值是1GB。
可以将reducer个数设置为固定值,无需Hive来计算得到这个值,Hive默认Reducer个数是3,可以通过属性mapred.reduce.tasks的值为不同的值来确定是使用较多还是较少的Reducer来缩短执行时间。

当在共享集群上处理大任务时,为了控制资源利用情况,属性hive.exec.reducers.max显得非常重要。一个Hadoop集群可以提供map和reduce资源个数是固定的。通过设置属性hive.exec.reducers.max可以阻止某个查询消耗太多的reducer资源。有必要将这个属性配置到$HIVE_HOME/conf/hive-site.xml文件中。对这个属性值大小的一个建议的计算公式如下:
(集群总reduce槽位个数 * 1.5) / (执行中的查询的平均个数)
1.5倍数是一个经验系数,用于防止未充分利用集群的情况。

JVM重用
Hadoop的默认配置通常是使用派生JVM来执行Map和Reduce的任务。JVM重用可以使得JVM实例在同一个job中重新使用N次。N的值可以在Hadoop的mapred-site.xml中进行设置

<property>
	<name>mapred.job.reuse.jvm.num.tasks</name>
	<value>10</value>
</property>

这个功能的缺点是,开启JVM重用将会一直占用使用到的task插槽,以便进行重用,直到任务完成后才能释放。如果某个“不平衡”的job中有某几个reduce task 执行的时间要比其他reduce task消耗的时间多得多的话,那么保留插槽就会一直空闲着却无法被其他的job使用,直到所有的task都结束了才会释放。

索引
索引可以用来加快含有group by语句的查询的计算速度。Bitmap索引一般在指定的列排重后的值比较小时进行使用。

动态分区调整
动态分区insert语句可以通过简单的select语句向分区表中创建很多新的分区。
动态分区调整如下:
首先,通常在hive-site.xml配置文件中设置动态分区模式为严格模式(也就是属性值为strict),开启严格模式的时候,必须保证至少有一个分区是静态的。

<property>
	<name>hive.exec.dynamic.partition.mode</name>
	<value>strict</value>
</property>

然后,可以增加一些相关的属性信息,可以通过如下属性来限制查询可以创建的最大动态分区个数:

<property>
	<name>hive.exec.max.dynamic.partitions</name>
	<value>300000</value>
</property>

<property>
	<name>hive.exec.max.dynamic.partitions.pernode</name>
	<value>10000</value>
</property>

还有一个配置是控制DataNode上一次可以打开的文件的个数。这个参数必须设置在DataNode的$HADOOP_HOME/conf/hdfs-site.xml配置文件中。
更改这个属性需要重启DataNode

<property>
	<name>dfs.datanode.max.xcievers</name>
	<value>8192</value>
</property>

推测执行
这个功能的目标是通过加快获取单个task的结果以及进行侦测将执行慢的TaskTracker加入到黑名单的方式来提高整体的任务执行效率。

Hadoop的推测执行功能由$HADOOP_HOME/conf/mapred-site.xml文件中的如下2个配置项控制着:

<property>
	<name>mapred.map.tasks.speculative.execution</name>
	<value>true</value>
</property>

<property>
	<name>mapred.reduce.tasks.speculative.execution</name>
	<value>true</value>
</property>

Hive本身也提供配置项控制reduce-side的推测执行

<property>
	<name>hive.mapred.reduce.tasks.speculative.execution</name>
	<value>true</value>
</property>

如果对于进行时的偏差敏感,则建议关闭,如果输入数据量很大需要执行长时间的map或者reduce task的话,启动推测执行造成的浪费是巨大的。
单个MapReduce中多个group by
另一个特别的优化是将查询中的多个group by操作组装到单个MapReduce任务中,如果想启动这个优化,则需要一组产公用的group by键:

<property>
	<name>hive.multigroupby.singlemr</name>
	<value>false</value>
</property>

虚拟列:
Hive提供了2中虚拟列:一种用于将要进行划分的输入文件名,另一种用于文件总的块内偏移量。当Hive产生了非预期的或null的返回结果时,可以通过这些虚拟列诊断查询。通过查询这些“字段”,用户可以查看到哪个文件甚至哪行数据导致出现问题:

hive> set hive.exec.rowoffset=true;
hive> SELECT INPUT__FILE_NAME, BLOCK__OFFSET__INSIDE__FILE, line from hive_text where line like '%hive%' limit 2;

第3种虚拟列提供了文件的行偏移量。需要通过如下参数显示的启用:

<property>
	<name>hive.exec.rowoffset</name>
	<value>true</value>
</property>

设置后就可以在类似于如下的查询中使用了

hive> SELECT INPUT__FILE__NAME, BLOCK__OFFSET__INSIDE__FILE, ROW__OFFSET__INSIDE__BLOCK 
	> from hive_text where line like '%hive%' limit 2;