Hive用的好,才能从数据中挖掘出更多的信息来。用过hive的朋友,我想或多或少都有类似的经历:一天下来,没跑几次hive,就到下班时间了。Hive在极大数据或者数据不平衡等情况下,表现往往一般,因此也出现了presto、spark-sql等替代品。这里重点讲解hive的优化方式,例如
优化分组:set hive.auto.convert.join=true;
优化表关联内存运行:/*+MAPJOIN(t1,t3,t4)*/ 复制代码
一. 表连接优化
-
将大表放后头
Hive假定查询中最后的一个表是大表。它会将其它表缓存起来,然后扫描最后那个表。因此通常需要将小表放前面,或者标记哪张表是大表:/ streamtable(table_name) / -
使用相同的连接键
当对3个或者更多个表进行join连接时,如果每个on子句都使用相同的连接键的话,那么只会产生一个MapReduce job。 -
尽量尽早地过滤数据
减少每个阶段的数据量,对于分区表要加分区,同时只选择需要使用到的字段。 -
尽量原子化操作
尽量避免一个SQL包含复杂逻辑,可以使用中间表来完成复杂的逻辑
二. 用insert into替换union all如果union all的部分个数大于2,或者每个union部分数据量大,应该拆成多个insert into 语句,实际测试过程中,执行时间能提升50%。示例参考如下:
insert overwite table tablename partition (dt= ....)
select ..... from ( select ... from A
union all
select ... from B union all select ... from C ) R
where ...;
复制代码
可以改写为:
insert into table tablename partition (dt= ....) select .... from A WHERE ...;
insert into table tablename partition (dt= ....) select .... from B WHERE ...;
insert into table tablename partition (dt= ....) select .... from C WHERE ...;复制代码
三. order by & sort byorder by : 对查询结果进行全局排序消耗时间长,需要set hive.mapred.mode=nostrictsort by : 局部排序,并非全局有序,提高效率。
四. transform+python一种嵌入在hive取数流程中的自定义函数,通过transform语句可以把在hive中不方便实现的功能在python中实现,然后写入hive表中。示例语法如下:
select transform({column names1})
using '**.py'
as {column names2}
from {table name}
复制代码
如果除python脚本外还有其它依赖资源,可以使用ADD ARVHIVE。
五. limit 语句快速出结果一般情况下,Limit语句还是需要执行整个查询语句,然后再返回部分结果。有一个配置属性可以开启,避免这种情况—对数据源进行抽样
hive.limit.optimize.enable=true --- 开启对数据源进行采样的功能
hive.limit.row.max.size --- 设置最小的采样容量
hive.limit.optimize.limit.file --- 设置最大的采样样本数复制代码
缺点:有可能部分数据永远不会被处理到
六. 本地模式对于小数据集,为查询触发执行任务消耗的时间>实际执行job的时间,因此可以通过本地模式,在单台机器上(或某些时候在单个进程上)处理所有的任务。
set oldjobtracker=${hiveconf:mapred.job.tracker};
set mapred.job.tracker=local;
set marped.tmp.dir=/home/edward/tmp;
set mapred.job.tracker=${oldjobtracker};
sql 语句
复制代码
可以通过设置属性hive.exec.mode.local.auto的值为true,来让Hive在适当的时候自动启动这个优化,也可以将这个配置写在$HOME/.hiverc文件中。当一个job满足如下条件才能真正使用本地模式: