一、输入端参数(控制读取时如何合并小文件,减少 Mapper 数量)
这 4 个参数共同决定 Hive 读取数据时,如何将大量物理小文件"打包"成较少的逻辑分片(InputSplit),从而避免为每个小文件都启动一个 Mapper。
1. hive.input.format
sql
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
-
作用:启用 Hive 的组合输入格式。
-
原理 :默认的
TextInputFormat等会为每个文件生成至少一个分片。CombineHiveInputFormat则可以将多个小文件合并到一个分片中,用一个 Mapper 处理多个文件。 -
重要性 :这是下面三个参数生效的前提 。如果不启用它,
mapred.min.split.size.per.node和per.rack将不起作用。
2. mapred.max.split.size
sql
set mapred.max.split.size=256000000; -- 256 MB
-
作用:设定一个分片的最大大小。
-
配合
CombineHiveInputFormat的含义 :在把小文件打包时,一个组合分片的总大小不会超过这个值。它的作用是防止合并后的分片过大、降低并行度。 -
效果:比如大量小文件总共有 1 GB,如果不设上限,可能全部合进一个分片,丢失并行性。设 256 MB 后,会被拆成约 4 个分片。
3. mapred.min.split.size.per.node
sql
set mapred.min.split.size.per.node=100000000; -- 100 MB
-
作用 :在同一个 DataNode 上合并小文件时,期望每个分片至少达到这个大小。
-
原理 :
CombineFileInputFormat会优先合并位于同一节点上的小文件。当组合文件总大小未达到 100 MB 时,会继续把该节点上更多小文件加入;如果某节点上所有文件加起来仍不足 100 MB,则会把它们全放进一个分片,不再等待。 -
效果:保证节点本地性(node-local)的前提下,尽可能让每个分片包含足够数据,减少 Mapper 数量。
4. mapred.min.split.size.per.rack
sql
set mapred.min.split.size.per.rack=100000000; -- 100 MB
-
作用 :当同一个节点上的文件不够凑满
min.split.size.per.node时,允许跨节点但在同一机架内继续合并,直到达到这个大小。 -
原理 :如果某个 DataNode 上只有 20 MB 的小文件,系统会尝试拉取同机架内其他节点的小文件,合并成一个大分片。这样牺牲了节点本地性(变成了机架本地性),但避免了产生零碎 Mapper。
-
取值 :通常和
per.node设成一样或稍大一点,此处设为相同的 100 MB,表示不论节点还是机架级别,都希望至少 100 MB 一个分片。
输入端总结 :
启用 CombineHiveInputFormat 后,系统会按"节点内达到 100 MB → 不足则机架内达到 100 MB → 但每个分片不超过 256 MB"的规则,把大量小文件合并处理,大幅减少 Mapper 数量。
二、输出端参数(控制写入后如何合并小文件,优化最终表文件)
这 4 个参数负责在 Hive 写入数据之后,检测文件大小并触发一次额外的合并作业,将过小的文件合并成大文件。
1. hive.merge.mapfiles
sql
set hive.merge.mapfiles = true;
-
作用 :对于Map-only 任务(没有 Reduce 阶段)产生的输出,自动合并小文件。
-
场景 :比如简单的
INSERT ... SELECT ...不涉及 Shuffle,或用了动态分区写入但只有 Mapper,结束后检查输出文件,若平均大小过小则启动合并作业。
2. hive.merge.mapredfiles
sql
set hive.merge.mapredfiles = true;
-
作用 :对于MapReduce 任务(包含 Reduce 阶段)产生的输出,自动合并小文件。
-
场景:大多数查询都有 Shuffle,即 Reduce 任务产生最终文件。该参数控制是否在 Reduce 结束后对输出目录进行小文件合并。通常两个参数都设为 true,以覆盖所有作业类型。
3. hive.merge.smallfiles.avgsize
sql
set hive.merge.smallfiles.avgsize=160000000; -- 160 MB
-
作用 :触发合并的阈值 。当作业输出文件的平均大小低于这个值时,Hive 才会认为存在小文件问题,并启动合并作业。如果平均大小已高于该值,则不会合并。
-
理解:这里设为 160 MB,意味着如果最终平均文件大小 ≥ 160 MB,就认为文件大小合理,无需合并。
4. hive.merge.size.per.task
sql
set hive.merge.size.per.task = 256000000; -- 256 MB
-
作用 :合并作业执行时,每个 Mapper 任务期望生成的文件大小。
-
原理 :合并作业本质上是再读一遍输出数据(只有 Map 阶段),然后按这个大小写入新文件。比如合并 1 GB 的小文件,会产出约
1024 MB / 256 MB ≈ 4个文件。 -
效果:直接决定了合并后的最终文件大小。设得越大会使文件数越少。
输出端总结 :
作业结束时,如果文件平均大小低于 160 MB,则触发一个 Map-only 合并作业,按每个任务 256 MB 输出,将小文件重写为数量更少、体积更大的文件。