最近批量刷数据的时候,由于集群资源紧张,需要控制一些 map 的数量,本文从底层代码触发,带大家了解一下 MR 是如何让切分 map 数的。
Hive 是基于 Hadoop 的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供完整的 sql 查询功能,可以将 sq l语句转换为 MapReduce 任务进行运行。当运行一个 hql 语句的时候,map 数是如何计算出来的呢?有哪些方法可以调整 map 数呢?
本文测试集群版本:cdh-4.3.0
hive 默认的 input format
在 cdh-4.3.0 的 hive 中查看 hive.input.format 值(为什么是hive.input.format?):
hive> set hive.input.format; hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
可以看到默认值为 CombineHiveInputFormat,如果你使用的是 IDH 的hive,则默认值为:
hive> set hive.input.format; hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;
CombineHiveInputFormat 类继承自 HiveInputFormat,而 HiveInputFormat 实现了 org.apache.hadoop.mapred.InputFormat 接口,关于 InputFormat 的分析,可以参考Hadoop深入学习:InputFormat组件.
InputFormat 接口功能
简单来说,InputFormat 主要用于描述输入数据的格式,提供了以下两个功能:
1)、数据切分,按照某个策略将输入数据且分成若干个 split,以便确定 Map Task 的个数即 Mapper 的个数,在 MapReduce 框架中,一个 split 就意味着需要一个 Map Task;
2)、为 Mapper 提供输入数据,即给定一个 split(使用其中的 RecordReader 对象)将之解析为一个个的 key/value 键值对。
该类接口定义如下:
public interface InputFormat<K,V>{ public InputSplit[] getSplits(JobConf job,int numSplits) throws IOException; public RecordReader<K,V> getRecordReader(InputSplit split,JobConf job,Reporter reporter) throws IOException; }
其中,getSplit() 方法主要用于切分数据,每一份数据由,split 只是在逻辑上对数据分片,并不会在磁盘上将数据切分成 split 物理分片,已经为大家精心准备了大数据的系统学习资料,从Linux-Hadoop-spark-......,需要的小伙伴可以点击实际上数据在 HDFS 上还是以 block 为基本单位来存储数据的。InputSplit 只记录了 Mapper 要处理的数据的元数据信息,如起始位置、长度和所在的节点。
MapReduce 自带了一些 InputFormat 的实现类:
hive 中有一些 InputFormat 的实现类,如:
AvroContainerInputFormat RCFileBlockMergeInputFormat RCFileInputFormat FlatFileInputFormat OneNullRowInputFormat ReworkMapredInputFormat SymbolicInputFormat SymlinkTextInputFormat H