• 关于hive当中的map输入数据和reduce输出数据的合并。


    最近在做要执行很复杂的sql.然后在文件输出的时候出现了一堆小文件:

    为啥要对小文件进行合并一句话总结为:文件数目过多,增加namenode的压力。因为每一个文件的元数据信息都是存在namenode上面的。所以要减少小文件的数据量。

    同时也是降低下一个程序处理这些小文件,启动和小文件一样数量的map数。增加jvm的压力。

    从两方面出发进行控制hive最终的文件大小:

    (1)从数据的文件大小控制,也就是控制map的数量:

    由于mapreduce中没有办法直接控制map数量,通过设置每个map中处理的数据量进行设置;reduce是可以直接设置的。 

    控制map和reduce的参数
    set mapred.max.split.size=256000000;           -- 决定每个map处理的最大的文件大小,单位为B
    set mapred.min.split.size.per.node=1024000000;  -- 节点中可以处理的最小的文件大小
    set mapred.min.split.size.per.rack=1024000000; -- 机架中可以处理的最小的文件大小
    set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat
    上面三个参数分别是map切分的文件大小。这个没有办法通过参数进行调整,这能动态的进行设置。第二个参数是对一个节点上面的文件进行合并,然后一个map的大小设置。第三个参数是对每个机架上面的文件进行合并。
    这三个参数的大小设置的顺序为:
    mapred.max.split.size <= mapred.min.split.size.per.node <= mapred.min.split.size.per.rack 

     (2)对于map数的控制是通过上面的参数进行设置的。但是这个只是控制map的数量,并不能控制reduce形成的数据文件的大小,因此我们还要在reduce端进行文件的合并操作

    方法1
    set mapred.reduce.tasks=10;  -- 设置reduce的数量
    方法2
    set hive.exec.reducers.bytes.per.reducer=1073741824 -- 每个reduce处理的数据量,默认1GB
    通过设置reduce的个数控制reduce端的文件的输出个数,还有一种方法是通过设置进入reduce端的数据的文件大小来控制文件的大小,来控制reduce的文件输出的个数。
    除了通过上面的例子参数对reduce的个数进行控制之外,我们还要控制在reduce端形成的文件大小,不能让小文件这种现象在出现。
        可以通过配置如下几个参数,合并Map和Reduce的结果文件,消除这些影响。
    • 控制每个任务合并小文件后的文件大小(默认256000000):hive.merge.size.per.task
    • 告诉hadoop什么样的文件属于小文件(默认16000000):hive.merge.smallfiles.avgsize
    • 是否合并Map的输出文件(默认true):hive.merge.mapfiles
    • 是否合并Reduce的输出文件(默认false):hive.merge.mapredfiles

    关于上免的参数的例子我做了一些实验,对于map数量的设置,直接通过set的方式进行设置即可,对于reduce端输出的文件大小的设置我的实验如下:

     create table loan_base_copy as
     select i.*
     FROM   loan_base c
     left  join   loan_special_repayment i on  i.loan_id = c.ID

    通过在hive的命令行执行上面的语句,然后转换为mapreduce任务。在这句sql当中,我们想控制在reduce端输出的文件大小。这里我设置了 hive.merge.smallfiles.avgsize的大小为256M。默认是16M。
    这句话的意思是在hive在执行之后reduce端的数据如果小于这个数,则会进行合并,然后按照我们给定的大小hive.merge.size.per.task 每一个任务合并的大小进行合并,他的值就是合并之后文件的大小。我们这里设置为512M.
    执行的结果和执行的过程如下:

     整个的reduce的合并是需要单独启动一个job的,然后将数据进行合并,至于我这里设置的数据为512M的文件大小,最后形成的文件大小不是512M。总而言之形成的不是小文件就好了。

    这里一定要搞清楚,只有reduce端形成的文件小于设置的hive.merge.smallfiles.avgsize的文件大小才实现文件的合并操作,合并的大小就是设置的hive.merge.size.per.task

  • 相关阅读:
    Codeforces 1132D
    Codeforces 670F
    Codeforces 670E
    Codeforces 670E
    Codeforces 670E
    Codeforces 670
    Codeforces 1138
    Codeforces 1114E
    力扣21.合并两个有序链表
    力扣538.把二叉树转换为累加树
  • 原文地址:https://www.cnblogs.com/gxgd/p/9838282.html
Copyright © 2020-2023  润新知