Hive 调优总结

1. 一般,能够经过设置属性hive.map.aggr值为true来提升聚合的性能。

hive.map.aggr=true;这个设置会触发在map阶段的“顶级”聚合过程。(非顶级的聚合过程将会在执行一个GROUP BY后进行)不过这个设置将须要更多的内存。node

2. 无需MapReduce

也就是所谓的本地模式。Hive能够简单的读取employees对应目录下的文件。例如:
select * from employees;
或者加where和limit也是能够的。
此外,若是属性hive.exec.mode.local.auto=true的话,Hive会尝试使用本地模式执行其余操做。(很是推荐)web

3. 浮点数比较问题FLOAT 0.2>DOUBLE 0.2

因为0.2对于FLOAT类型是0.2000001,而对于DOUBLE类型是0.200000000001,当两者比较是FLOAT会转成DOUBLE 0.200000100000,这个值实际要比0.200000000001大。sql

规避办法:缓存

  1. 对于TEXTFILE文件,读取字符串“0.2”,能够直接在表模式中定义类型为DOUBLE。
  2. 显式地指出0.2为FLOAT类型。如:cast(0.2 AS FLOAT)
  3. 和金钱相关都避免使用浮点数
    Note: 对于浮点数比较,需保持极端谨慎的态度。

4. LIKE与RLIKE

LIKE模糊查询,RLIKE是一个扩展支持正则匹配app

5. JOIN语句,Hive只支持等值链接,即ON a.id = b.id,

缘由是因为MapReduce很难实现这种非等值的链接。jvm

大多数状况下,Hive会对每对JOIN链接对象启动一个MapReudce任务。例:a JOIN b ON a.ymd = b.ymd JOIN c ON a.ymd = c.ymd。首先启动MapReduce对a和b进行链接操做,而后再启动一个MapReduce将第一个MapReduce job的输出和c进行链接操做。这是由于Hive老是按照从左到右的顺序执行的。ide

6. JOIN优化

  1. 自动优化:当对3个或者更多的表进行JOIN链接时,若是每一个ON子句都是用相同的链接键的话,那么只会产生一个MapReduce job。如上例中都是用ymd做为键,就会自动优化为1个MapReduce job。
  2. 在作链接操做时,Hive会将前面对表缓存,而后扫描最后的表进行计算。所以,用户须要保证连续查询中的表的大小从左到右依次增长的(小 JOIN 中 JOIN 大)。
  3. 经过“标记”显示地告诉优化器哪张表是大表。SELCET /*+STREAMTABLE(a)*/a.id, a.name from table1 a JOIN table2 b ON a.id = b.id;
  4. map-side JOIN(很是推荐)
    彻底将小表放到内存,从而省略掉链接的reduce过程。
    使用标记/*+MAPJOIN(d)*/
    set hive.auto.convert.join=true;
  5. OUTER JOIN 优化,尽可能不对大量NULL的字段进行WHERE的条件。WHERE在JOIN后执行,应该只做用于过滤那些非NULL字段。
  6. LEFT SEMI-JOIN
    Hive不支持... WHERE a.id IN (SELECT d.id from table_d d) 但可使用左半开链接SELECT a.id, a.name FROM table_a a LEFT SEMI JOIN table_d d ON a.id = d.id;注意,SELECT和WHERE都不能用到右边表的字段。SEMI-JOIN比INNER JOIN更高效,由于:对于左表中一条指定的记录在右表中一旦找到匹配的记录就会中止扫描。
  7. 笛卡尔积JOIN(无ON子句):Hive没法优化

7. ORDER BY, SORT BY, DISTRIBUTE BY

ORDER BY全局排序是很是耗时的,如非必要可使用SORT BY(reduce中局部排序)替代,但在不一样的reducer中数据可能会有重合。DISTRIBUTE BY控制map的输出在reducer中是如何划分的,一般不用关心。能够结合SORT BY,将相同的数据发送到同一个reducer中,这样能够避免不一样reducer中的数据重合。SELECT s.ymd, s.symbol, s.price FROM stocks s DISTRIBUTE BY s.symbol SORT BY s.symbol ASC, s.ymd ASC;
ASC是能够省略的。Hive要求DISTRIBUTE BY须要写到SORT BY以前。svg

8. 类型转换不合法的状况

cast(value AS FLOAT)若是value不是合法的FLOAT,Hive会返回NULL函数

9. 分桶的优势

  • 分区提供一个隔离数据和优化查询的便利的方式。不过,并不是全部的数据集均可以造成合理的分区,特别是肯定合适的划分大小。
  • 分桶,是将数据集分解成更容易管理的若干部分的另外一个技术。经过给定字段(user_id)的哈希值放到同一个桶内。同一个user_id就会存在于同一个桶内。
  • 若是没有使用hive.enforce.bucketing属性,就须要本身设置和分桶个数相匹配的reducer个数,例如:使用set mapred.reduce.tasks=96,而后须要在SELECT语句后增长CLUSTER BY
  • 由于桶的数量是固定的,因此他没有数据波动,桶对于抽样再适合不过。
  • 分桶有利于高效的执行map-side JOIN。

10. 限制调整

LIMIT在不少状况下仍是须要执行整个查询语句,而后再返回部分结果。Hive提供一个设置在使用LIMIT语句是,能够对源数据进行抽样:hive.limit.optimize.enable=true,一旦设置为true,那么还有连个参数能够控制这个操做hive.limit.orw.max.sizehive.limit.optimize.limit.file
惟一的缺点,有可能输入中有用的数据永远不会被处理到。例如:任意的一个须要reudce步骤的查询,JOIN和GROUP BY操做,以及聚合函数的大多数调用,将会产生很不一样的结果。也许这个差别在不少状况下是能够接受的,可是重要的是要理解。性能

11. 并行执行

Hive会将一个查询转换为多个MapReduce阶段,在无必要依赖的阶段之间能够并行执行。hive.exec.parallel=true开启。

12. 调整mapper和reducer个数

  1. Hive是按照输入的数据量大小来肯定reducer个数的,咱们能够经过dfs -count命令老计算输入量大小。
  2. 有些状况map产生比实际多得多的数据,那么根据输入数据量来肯定reducer个数就显得有些少了。所以,在map阶段尽可能过滤掉不须要的数据就更好的知足reduce的计算。
  3. 一般也会经过hive.exec.reducers.max设置reduce个数的上限,防止耗尽共享集群的资源。

13. JVM 重用

因为每个MapReduce的task都要启动一个JVM,若是是有不少小文件的场景,就会消耗过多的时间在初始化资源上。能够经过mapred.job.reuse.jvm.num.tasks指定重用JVM的个数。缺点:直到全部任务完成后才会释放。一旦出现某个“不平衡”的job一直没法完成工做(倾斜),其余的reduce task须要一直等待。

14. 索引

Hive v0.8.0 版本后增长了bitmap索引实现。索引能够用来加快GROUP BY的查询速度。

15. 推测执行

16. 单个MapReduce中多个GROUP BY

试图将多个GROUP BY操做组装到单个MapReduce。若是想启动这个优化,那么须要一组经常使用的GROUP BY键:hive.multigroupby.singlemr=false

17. 虚拟列

Hive提供了2种虚拟列便于定位数据和调试:一种用于将要进行划分的输入文件名,另外一种用于文件中的块内偏移量。

hive> select INPUT__FILE__NAME, BLOCK__OFFSET__INSIDE__FILE,order_id from orders limit 10;
OK
input__file__name	block__offset__inside__file	order_id
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 90 2539329
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 114 2398795
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 142 473747
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 169 2254736
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 197 431534
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 224 3367565
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 252 550135
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 279 3108588
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 307 2295261
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 334 2550362
Time taken: 0.068 seconds, Fetched: 10 row(s)

第三种虚拟列提供了文件的行偏移量,须要经过参数显示的启动。

<property>
    <name>hive.exec.rowoffset</name>
    <value>true</value>
</property>
hive> select INPUT__FILE__NAME, BLOCK__OFFSET__INSIDE__FILE, ROW__OFFSET__INSIDE__BLOCK,order_id from orders limit 10;
OK
input__file__name	block__offset__inside__file	row__offset__inside__block	order_id
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 90 0 2539329
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 114 0 2398795
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 142 0 473747
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 169 0 2254736
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 197 0 431534
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 224 0 3367565
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 252 0 550135
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 279 0 3108588
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 307 0 2295261
hdfs://node1:9000/user/hive/warehouse/orders/orders.csv 334 0 2550362
Time taken: 1.191 seconds, Fetched: 10 row(s)
hive>

18. HiveQL

Hive不支持行级插入操做、更新操做和删除操做。Hive也不支持事务。

19. 关于分区

使用过多的分区可能致使大量的文件。所以,一个理想的分区方案不该该致使产生太多的分区和文件夹目录,而且每一个目录下的文件应该足够得大,应该是文件系统中块大小的若干倍。 按照时间分区,随着时间的推移分区数量的增加是“均匀的”。一个分区是一个目录,一个分桶是一个文件。