能否控制HortonWorks HDP 3.4.1托管表的HDFS文件大小?
问题拆解与优化方案
我来帮你分析下这个CTAS操作的性能差异问题,以及对应的解决思路:
背后的核心原因
首先,这个现象的本质是Hive对托管表和外部表的文件管理策略差异,再加上HDP版本升级后的参数默认值变化:
- 对于托管表(MANAGED TABLE):在高于HDP 3.0.1的版本中,Hive默认开启了小文件合并逻辑——当你用
CREATE TABLE AS生成托管表时,系统会自动启动合并步骤,把源表的多个小文件合并成更大的文件(你这里最终生成1.2GB文件就是这个逻辑的结果)。这个合并步骤由Reducer执行,而默认Reducer数量可能只有2个,导致这一步耗时占比极高。 - 对于外部表(EXTERNAL TABLE):Hive的设计逻辑是“用户自主管理存储”,所以默认不会触发任何自动合并操作,直接把查询结果按原有并行度输出,因此速度极快。
- HDP 3.0.1版本没有这个现象,是因为当时的Hive默认关闭了托管表CTAS的自动合并参数,所以不会启动额外的合并Reducer。
具体控制这个行为的关键参数有:
hive.merge.tezfiles:Tez引擎下是否合并输出文件(托管表默认开启)hive.merge.size.per.task:合并后单个文件的目标大小(决定了最终生成文件的大小)hive.merge.smallfiles.avgsize:当平均文件大小低于这个值时触发合并
针对性优化方案
根据你的需求,有几种不同的优化路径可选:
1. 临时关闭合并(快速解决当前场景)
如果只是想让这次CTAS托管表的速度和外部表一样,可以在执行语句前临时关闭合并参数:
SET hive.merge.tezfiles=false; SET hive.merge.mapfiles=false; SET hive.merge.mapredfiles=false;
执行完这些设置后再运行你的CREATE TABLE AS SELECT ...,就会跳过合并步骤,直接输出和源文件并行度一致的结果,耗时会大幅降低。
2. 调整合并参数,提升合并效率
如果需要保留合并小文件的功能(比如优化后续查询性能),可以调整合并相关的参数来降低耗时:
-- 增加Reducer数量,让合并并行处理 SET hive.exec.reducers.max=8; -- 根据你的集群资源调整,比如8-16个 -- 调整单个合并文件的大小,减少单个Reducer的处理压力 SET hive.merge.size.per.task=128000000; -- 比如设为128MB
这样合并步骤会用更多的Reducer并行处理,耗时占比会明显下降。
3. 提前合并源表小文件(从根源解决)
既然源表本身是多个小文件,你可以先对源表做一次小文件合并,比如针对ORC格式的表:
ALTER TABLE your_source_table CONCATENATE;
或者用INSERT OVERWRITE的方式重新生成源表的文件:
INSERT OVERWRITE TABLE your_source_table SELECT * FROM your_source_table;
合并完源文件后,后续的CTAS操作就不需要再做合并,整体性能会提升。
4. 改用外部表(如果业务允许)
如果你的业务场景不需要Hive托管文件(比如文件要保留在指定路径、后续要被其他系统访问),直接使用CREATE EXTERNAL TABLE AS SELECT ...就可以,天然不会触发合并,性能最优。
内容的提问来源于stack exchange,提问作者rbigley
相关产品推荐
相关产品推荐

