0455-如何在Hadoop中处理小文件-续

本文详细介绍了如何在Hadoop中处理小文件,包括小文件产生的原因、分区设计、文件格式与压缩的选择,以及如何通过Hive最小化小文件生成和合并已有的小文件。建议采用动态文件合并和强制文件合并策略,同时利用FileCrusher工具进行高效合并,以优化HDFS性能和扩展性。
摘要由CSDN通过智能技术生成

Fayson的github: https://github.com/fayson/cdhproject

推荐关注微信公众号:“Hadoop实操”,ID:gh_c4c535955d0f,或者扫描文末二维码。

Fayson在前面的文章《0403-如何在Hadoop中处理小文件》和《0405-如何使用Impala合并小文件》中介绍了什么是Hadoop中的小文件,以及常见的处理方法。这里Fayson再补充一篇文章进行说明。

HDFS中太多的小文件往往会带来性能下降以及扩展性受限问题,为了避免这个问题,我们一般需要控制每个文件尽可能的接近HDFS block大小比如256MB,或者是block size的几倍。

在抽取数据时,应尽可能调整抽取管道以保存较少数量的大文件,而不是大量的小文件。如果你做不到,比如实时场景在抽数的时候总是一小批一小批,那只能事后定期的去合并这些小文件。

本文Fayson主要介绍如何最小化小文件生成以及如何合并小文件。

1.小文件是如何产生的

以下是产生小文件的典型场景:

1.滴漏数据(Trickling data) - 数据是以小批量的形式进行增量抽取会导致小文件的产生,那只能事后定期使用一些额外的作业去合并这些小文件。

2.大量的map或者reduce任务 - 大量map或者reduce任务的MapReduce作业或Hive查询很多文件,比如Map-Only的作业有多少个map就会生成多少个文件,如果是Map-Reduce作业则有多少个reduce就会生成多少个文件。

3.过度分区的表 - 比如一个Hive表有太多分区,每个分区下只有几个文件甚至只有一个小文件,这时考虑降低分区的粒度比如从按照天分区改为按照月份分区。

4.上述情况的组合 - 如果上面三种情况组合出现,会加剧小文件问题。比如过度分区的Hive表,每个分区下都是很多个小文件而不是大文件。

2.分区设计

分区是指将大型Hive/Impala表物理拆分为多个更小的,容易管理的部分。当根据分区进行查询时,只需要扫描必要分区的数据,从而显著提升查询性能。

在HDFS中尽量保存大文件的原则同样适用于分区表的每个分区,我们应尽量保证每个分区对应的HDFS目录下的文件都较大。所以在设计表分区时,应该注意一下几点:

1.避免过度分区表。在确定分区的粒度时,请考虑每个分区将存储的数据量。确保每个分区保存的文件都是大文件(256MB的文件或者更大),即使这样设计会导致分区粒度变得更粗,比如从按天分区变为按月分区。

2.对于数据量较小(几百MB)的表,请考虑创建一个非分区表。这样即使我们只扫描单个文件夹下的所有文件,也会比处理分散在数个分区中的数百甚至数千个文件性能要好。

3.文件格式和压缩

根据过往的经验,有些大的集群碰到小文件问题,往往是大量的Hive/Parquet表以未压缩的方式存储,并使用TEXTFILE文件格式。

从本质上说,HDFS中的文件或者Hive/Impala的表文件你选择何种文件格式,对于小文件问题没有直接关系。然而,使用低效的文件格式(比如TEXTFILE)和没有压缩的数据会从侧面影响小文件问题甚至是加剧,从而影响集群的性能和可扩展性,具体包含以下几个方面:

1.使用低效的文件格式,尤其是未压缩的文件格式,会导致HDFS空间使用量的增加以及NameNode需要跟踪的块数量的增加。如果文件很小,由于要存储的原始数据量较大,可能会有更多的小文件。

2.由于读取和写入大量数据而导致更高的IO争用。

3.从非常宽的表(具有大量字段的表)中读取非列式存储格式(TextFile,SequenceFile,Avro)的数据要求每个记录都要从磁盘中完全读取,即使只需要几列也是如此。像Parquet这样的列式格式允许仅从磁盘读取所需的列,这样可以显著提高性能。

为了确保性能和高效存储之间的良好平衡,答应Fayson,请尽量使用PARQUET格式创建表,并确保在向其写入数据时启用数据压缩(除非对Hive / Impala表使用的存储格式有特定要求)。

在Hive中,使用以下示例创建Parquet表,并确保在插入时使用Snappy压缩来压缩数据。

# Hive

# Create table
CREATE TABLE db_name.table_name (
...
)
STORED AS PARQUET
LOCATION '/path/to/table';

# Create table as select
SET parquet.compression=snappy; 

CREATE TABLE db_name.table_name
STORED AS PARQUET
AS SELECT ...;

# Insert into/overwrite table
SET parquet.compression=snappy; 

INSERT INTO TABLE db_name.table_name
SELECT ...;

在Impala中,使用以下语法:

# Impala

# Create table
CREATE TABLE db_name.table_name (
.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值