美文网首页
hive on tez中map任务的数量计算

hive on tez中map任务的数量计算

作者: 程序员的交流电 | 来源:发表于2020-09-23 07:49 被阅读0次

    首先说明,本篇文章的内容不是原创,因为原文质量比较好,因此想进一步的归纳总结, 原文链接 https://www.cnblogs.com/zackstang/p/11435039.html

    hive on tez的map的数量计算

    在hive里面执行一个query时,我们可以发现,hive的执行引擎在使用tez和MR的时候,两者生成的mapper数量差异较大。主要的原因是tez会对inputsplit做grouping的操作,将多个inputsplit组合成为更少的groups,然后为每一个group生成一个mapper任务,而不是像MR一样,为每一个inoutsplit生成一个mapper任务。下面,我们通过日志来分析一下整个过程。

    1.MR模式

    在MR模式下生成了116个



    对应的日志为:
    Input size for job job_1566964005095_0003 = 31733311148. Number of splits = 116
    在MR中,使用的是hadoop的FileInoutFormat,所以诺是一个文件大于一个Block的大小,则会被切分为多个inputSplit;诺是一个文件小于一个block的大小,则为一个inputsplit。在这个案例中国,文件个数为14个,每个为2.1G,一共是29.4G大小,生成的inputSplit数为116个,也就是说,这里的inputSplit为256M,这里要说明一下,MR中的默认的Input的spilt是128M,但是我们可以修改,通常修改为2的倍数,在这里HIve的inputSplitSize为256M。

    2.Tez模式

    而在tez模式下,生成了map任务为32个



    首先可以看到要处理的文件是14个,初始的splits的个数为476个(意味着,在Tez中设置的splitSize为64M)
    日志如下:
    |mapred.FileInputFormat|: Total input files to process : 14
    |io.HiveInputFormat|: number of splits 476

    获取到splits为476个之后,Driver开始计算可用的slots(container)数,这里计算得到3个slots,并打印waves为1.7,

    在这个场景中,,集群的资源是8Vcores,12G内存,tez的capacity_scheduler中指定的user limit factor是0.5,也就是说最多可用内存为6个,在tez Driver中,申请的container资源的单位为Default Resources=<memory:1536, vCores:1>,这里要看Default Resource

    所以理论上,可以申请到的container的个数为4个(6G/1536M=4),但是AM需要占用一个,所以用于计算的available slot(container)为3个。
    在计算出可用的slots为3个后,Tez使用的split-waves(由tez.grouping.split-waves指定,默认值为1.7)计算出指定的预估的Map任务数目为 3*1.7=5 个task,对应的日志如下,
    |tez.HiveSplitGenerator|: Number of input splits: 476. 3 available slots, 1.7 waves. Input format is: org.apache.hadoop.hive.ql.io.HiveInputFormat
    |tez.SplitGrouper|: Estimated number of tasks: 5 for bucket 1

    Grouping Input Splits

    在tez分配任务的时候,不会像MR为每个split生成一个map任务,而会将多个split进行grouping。让map任务可以更高效的完成。首先tez会根据计算得到 estimate number of tasks = 5 预估task的个数为5,这个5是有3个slot*split-waves1.7得到的,将476个splits聚合为5个SplitGroup,生成5个mapper执行任务。

    但是这里还需要考虑另外的一个值:lengthPerGroup,,tez会检查lengthPerGroup是否在Tez.grouping.min-size(默认值为50,)和tez.grouping.max-size(默认为1G)之间。如果超过max-size,则将lengthPerGroup设置为max-size,如果小于min-size,则将lenghtPerGroup设置为min-size。

    在这样的场景下,数据总大小为29.5GB左右,预估为5个Group,则每个group需要处理的数据为5.9G,超过了Max splitLenght = 1G 所以 lengthPreGroup的大小为1G,splitLength的大小也要按照1G来划分,计算出所需要的numsplits为30个左右,每个splitGroup为1G。

    在计算出每个split group为1G后, 由于原来的splits的总数为476个,所以需要将476个split进行grouping的操作,是的每个group大小为1个左右,按照这个方法,逾期的split个数为30个,(这里的30的结果是预估,没有考虑文件个数等,所以不一定是最终的splits),且最终计算出每个group包含原先的15个split,也就是numSplitsInGroup=15,相关日志如下:
    |grouper.TezSplitGrouper|: Grouping splits in Tez
    |grouper.TezSplitGrouper|: Desired splits: 5 too small. Desired splitLength: 6346662229 Max splitLength: 1073741824 New desired splits: 30 Total length: 31733311148 Original splits: 476
    |grouper.TezSplitGrouper|: Desired numSplits: 30 lengthPerGroup: 1057777038 numLocations: 1 numSplitsPerLocation: 476 numSplitsInGroup: 15 totalLength: 31733311148 numOriginalSplits: 476 . Grouping by length: true count: false nodeLocalOnly: false

    原先总数为476,对splits进行group之后,每个group包含15split,最终group的数目计算为476/15=32个,也就是最终生成的mapper数量
    日志如下:
    |tez.SplitGrouper|: Original split count is 476 grouped split count is 32, for bucket: 1
    |tez.HiveSplitGenerator|: Number of split groups: 32

    所以在Tez中,inputSplit 数目虽然是476个,但是最终仅生成了32个map任务用于处理所有的 475个inputSplits,减少了过多mapper任务会带来的额外开销。

    split waves

    这里为什么要定义一个split waves,使用这个值可以让Driver申请更多的Container,比如本场景中,本来仅仅只有3个slots可以使用,但是会根据这个乘数在多申请两个Container的。但是这样做的原因是什么呢。

    1. 首先他可以让分配资源更灵活,:比如集群之后新增了计算节点,其他任务十分了资源等,所有即使有部分的map任务在等待资源,它们也会在后续被分配到资源的。
      2.将数据分配给跟多的mapper,提高程序执行的并行度,减少map任务处理的数据量,并缓解由于少部分map任务执行较慢,导致的任务整体变慢的情况。

    相关文章

      网友评论

          本文标题:hive on tez中map任务的数量计算

          本文链接:https://www.haomeiwen.com/subject/rjgiyktx.html