Hive小文件问题

  • Post author:
  • Post category:其他




1、小文件产生的原因


  • 数据源本身有很多小文件


  • reduce数量多导致生成的小文件增多


  • 使用动态分区导致小文件增多



2、小文件危害


  • HDFS内存资源消耗过大,并限制了数据存储规模

    :在HDFS中,具体的文件保存在datanode节点中,在

    namenode

    节点中会有一个内存对象与之对应,用于存储文件的元信息,如位置、大小、分块等,每个对象大约占用150个字节。因此,过多的碎片文件会使得namenode消耗大量的内存资源用于管理文件元数据,性能也会因此受到影响,这样namenode的内存容量严重制约了集群的发展。

  • 数据的访问更加耗时

    :处理小文件并非Hadoop的设计目标,HDFS的设计目标是

    流式访问

    大数据集。在HDFS中,每次读写文件都需要先从namenode获取文件元数据信息,然后与datanode建立连接。而访问大量的小文件会经常会需要大量的定位寻址操作,不断地在datanode间跳跃去检索小文件。这种访问方式严重影响性能。

  • 数据运算的时间成本以及计算资源成本更高

    :在计算层面,小文件越多,意味着MapReduce执行任务时需要创建的map也会越多,这样,任务的启动与释放将耗费大量时间。同时,每一个map都会开启一个JVM虚拟机用于执行任务,带来的调度以及计算成本也更高了。



3、解决思路



1)从源端限制小文件生成



2)对已产生的小文件进行处理

  • Hive参数调节

    在这里插入图片描述
  • 动态分区插入式,保证有静态分区,不要误判产生大量分区
  • 按照分区合并导入:Hive SQL提供了distribute by语法用于控制map端如何拆分数据给reduce,根据distribute by后面的列对应的reduce个数进行分发,默认采用hash算法,在使用上如配合分区表的分区列 insert select到结构与源表一样的目标表,可以在目标表对数据按分区进行压缩;如果原表有大量小文件,在导入目标表的时候也会产生大量小文件。如果有分区如dt、hour,可以使用 distribute by dt,hour,

    保证每小时数据在一个reduce里面
insert into test select * from table distribute by dt(rand()*5)
  • 定期合并数据:类似于增量导入数据,会存在小文件,需要进行一天或者一周的定时文件合并
  • 覆盖原表数据:
  • 针对ORC存储的表:

    alter table test [partition(…)] concatenate



版权声明:本文为Stannis原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。