Hive学习笔记(4)——调优

常用参数设置

  • set mapred.recduce.tasks = 1;:设置默认启动的Reducer数量。
  • set hive.mapred.mode = strict/nonstrict;:开启严格模式,如果设置为strict,会禁止以下情况提交任务,以防止触发低效的MapReduce任务:
    • 笛卡尔积JOIN
    • ORDER BY不含LIMIT
    • 读取分区表没有指定分区字段。
  • set hive.merge.mapredfiles = true;:在map任务开始和Reduce任务结束时合并小文件,防止开启过多的map任务。
  • set hive.merge.size.per.task = 256000000;:每个任务合并后文件的大小,据此大小确定Reducer的个数。
  • set hive.merge.smallfiles.avgsize=64000000;:需要合并的小文件群的平均大小。
  • set hive.exec.compress.intermediate = true;:开启中间压缩,减少job中Map和Reduce Task的数据传输量。
  • set hive.exec.mode.local.auto = true;:开启本地模式,可以在处理小数据集时避免使用MapReduce。
  • set hive.exec.dynamic.partition = true;:打开动态分区,默认关闭。
  • set hive.exec.dynamic.partition.mode = strict/nonstrict;:动态分区若采用严格模式,则至少要包含一个静态分区。

存储和压缩方式

  • 行式存储:数据按行连续存储,行查询效率高、列查询效率低,适合SELECT *比较多的情况,数据压缩效率低。默认的TextFileSequenceFile均为行式存储。
  • 列式存储:数据按列连续存储,列查询效率高、行查询效率低,适合SELECT col_name比较多的情况,数据压缩效率高。ORCFileParquet为列式存储。
  • 压缩方式:Hive支持多种压缩方式,如SnappyLZ4LZOGZIPBZIP2等。压缩数据能减少磁盘空间占用、降低网络IO和磁盘IO,提升传输速度。

在实际项目开发中,Hive表存储格式一般选择ORCFileParquet,压缩方式一般选择Snappy

Hive查看执行计划

EXPLAIN [EXTENDED]可以查看Hive如何把任务转化为MapReduce任务:

  1. 显示抽象语法树AST
  2. 显示STAGE依赖关系:一个Hive任务包含多个STAGE,不同STAGE之间存在依赖关系,越复杂的任务会包含越多的STAGE,需要更多的时间完成;
  3. 显示每个阶段的具体描述,例如SelectOperatorGroupByOperator及其对应的字段名称。

数据倾斜

分布式数据处理希望数据平均分布到每个处理节点,但是由于数据本身或者分布算法的问题,每个节点分配到的数据量不均衡,导致分布式处理的性能大打折扣。

解决GROUP BY的数据倾斜

  • set hive.map.aggr = true;开启Map端聚合参数设置。
  • set hive.groupby.skewindata = true;开启负载均衡,默认关闭。
  • 开启负载均衡,会产生两个MapReduce任务,第一个MapReduce Job会把Map输出的结果随机分配到Reduce中,达到负载均衡的目的;第二个MapReduce Job根据预处理的数据结果按照GROUP BY键分布到Reduce中,保证相同的键分布到同一个Reduce中,完成聚合操作。

解决COUNT DISTINCT的数据倾斜

  • 由于需要去重,会把Map阶段的输出分布到一个Reduce Task上,因此可以转化为先GROUP BY去重、再COUNT(1)的方式来优化。

JOIN优化

  • 多表连接使用同一个字段,Hive会进行优化,把多表连接在一个Map/Reduce上进行:假定最后一个表是最大的表,将前面的表缓存起来,扫描到最后的表再进行计算。因此需要保证查询的表从左到右依次增大。也可以通过/*+STREAMTABLE()*/来标识最大的表。

大表JOIN小表优化

  • set hive.auto.convert.join = true;开启mapjoin功能,默认是开启的。
  • mapjoin hint:/*+MAPJOIN(b)*/(mapjoin多个表:/*+MAPJOIN(b, c, d)*/)。
  • 在Map阶段进行JOIN,把小表全量复制到每个Map节点的内存中,在Map中完成JOIN,无需Reduce过程,因此不会产生数据倾斜。
  • 通过设置set hive.auto.convert.join.noconditionaltask.size来确定小表的大小是否满足条件,默认25MB,一般不能超过1GB。

大表JOIN大表优化

  • 方法1:根据业务需求,限制行数、列数,使得过滤后的表满足mapjoin的条件。
  • 方法2:针对NULL值过多造成的数据倾斜,对NULL值取随机数,随机分发到不同的Reducer上。
  • 方法3:倍数B表,再取模JOIN
  • 方法4:动态一分为二,不倾斜的正常JOIN,倾斜的找出来后mapjoin,然后UNION ALL

其他

  • 尽量不使用SELECT *,用到哪些列指定哪些列。
  • WHERE尽量添加过滤条件,去掉无关的数据行。
  • 输入文件不要是大量的小文件,否则开启过多的Map节点造成性能上的浪费。