1、explain _query与 explain extended _query


用于查看hive对hql的解析,包括执行阶段、执行任务和任务属性

explain select name from test
explain  extended select name from test
...

2、limit

在使用客户端查询hive数据时,经常会用到limit限制输出数据数目,很多情况下会执行全表查询,而只返回很少一部分数据,所以这种操作很浪费时间,所以可以对这个操作进行优化,

<property>
<name>hive.limit.optimize.enable</name>
<value>true</value>
<description>Whether to enable to optimization to
try a smaller subset of data for simple LIMIT first.</description>
</property>

这个参数保证hive使用limit查询时进行抽样查询,不需要进行全表查询,节省很多时间。缺点是有些需要的数据可能被忽略掉(抽样)

一下两个参数配合使用:

hive.limit.row.max.size  每一行最大长度

hive.limit.optimize.limit.file:  从多少个数据文件中进行抽样

3、Local Mode

执行本地化,当查询处理很小的数据集合时,优先进行本地化处理

<property>
<name>hive.exec.mode.local.auto</name>
<value>true</value>
<description>
Let hive determine whether to run in local mode automatically
</description>
</property>

4、并行化执行

每个查询被hive转化成多个阶段,有些阶段关联性不大,则可以并行化执行,减少执行时间

<property>
<name>hive.exec.parallel</name>
<value>true</value>
<description>Whether to execute jobs in parallel</description>
</property>

5、Strict 模式(严格)

如果把 hive.mapred.mode 设置成 strict模式,则有三种查询不能操作


(1)当在有分区的表进行查询操作时,如果WHERE字句中没有一个分区过滤条件,则hive不允许执行这个操作

hive> SELECT DISTINCT(planner_id) FROM fracture_ins WHERE planner_id=5;
FAILED: Error in semantic analysis: No Partition Predicate Found for
Alias "fracture_ins" Table "fracture_ins"

(2)当查询语句中有ORDER BY字句时,则必须有LIMIT字句。因为ORDER BY 字句把所有的结果送到一个reducer进行排序,使用limit可以减少执行时间

hive> SELECT * FROM fracture_ins WHERE hit_date>2012 ORDER BY planner_id
> LIMIT 100000;
... normal results ...

(3)求表的笛卡尔积(Cartesian product)时,必须使用ON字句,而不能用WHERE字句替代

hive> SELECT * FROM fracture_act JOIN fracture_ads
> ON (fracture_act.planner_id = fracture_ads.planner_id);
... normal results ...

6、调整Mappers 和Reducers数目

在hive中,有些查询语句仅仅需要map任务,而不需要reduce数目,所以要根据具体的查询调整reduce数目。比如像group by 这样的字句就需要reduce任务。

hive> SELECT pixel_id, count FROM fracture_ins WHERE hit_date=20120119
> GROUP BY pixel_id;
Total MapReduce jobs = 1
Launching Job 1 out of 1
Number of reduce tasks not specified. Estimated from input data size: 3

默认情况下,reduce任务数目是根据输入数据大小进行计算的,每个reducer默认处理的数据是1GB(hive.exec.reducers.bytes.per.reducer),利用上例,修改默认值为750MB,则有如下输出

hive> set hive.exec.reducers.bytes.per.reducer=750000000;
hive> SELECT pixel_id,count(1) FROM fracture_ins WHERE hit_date=20120119
> GROUP BY pixel_id;
Total MapReduce jobs = 1
Launching Job 1 out of 1
Number of reduce tasks not specified. Estimated from input data size:  4

reducer数目估计值为4


mapred.reduce.tasks  这个值是调整默认reducer数目的参数,reducer数目不易过少,这样不会充分利用集群的并行化。同样,reducer数目不易过多,因为初始化和调度reducer任务会占很多时间,同时防止一个较大的任务占据了集群的较多的资源,有如下参数可以限制每个job最多可有的reducer数目:

hive.exec.reducers.max

计算方式

(Total Cluster Reduce Slots * 1.5) / (avg number of queries running)

7、JVM重利用

<property>
<name>mapred.job.reuse.jvm.num.tasks</name>
<value>10</value>
<description>How many tasks to run per jvm. If set to -1, there is no limit.</description>
</property>

JVM重利用可以是JOB长时间保留slot,知道作业结束,这在对于有较多任务和较多小文件的任务是非常有意义的,减少执行时间。当然这个值不能设置过大,因为有些作业会有reduce任务,如果reduce任务没有完成,则map任务占用的slot不能释放,其他的作业可能就需要等待。

8、索引


9、动态分区优化


10、虚拟列

hive表提供两个虚拟列,一个是输入的文件名(分片)、一个是文件块内偏移

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;
har://file/user/hive/warehouse/hive_text/folder=docs/
data.har/user/hive/warehouse/hive_text/folder=docs/README.txt 2243
http://hive.apache.org/
har://file/user/hive/warehouse/hive_text/folder=docs/
data.har/user/hive/warehouse/hive_text/folder=docs/README.txt 3646
- Hive 0.8.0 ignores the hive-default.xml file, though we continue

通过这两个虚拟列,可以确定有异常的文件名和哪一行