jvm调优参数HIVESQL产⽣的⽂件数量及参数调优
  产⽣背景:sqoop抽取oracle数据到hive表时,只能写⼊到固定分区(--hive-partition-key #hive分区字段 --hive-partition-value #hive分区值)。于是先把数据抽取到⼀张增量表,然后从增量表动态写⼊分区表。
de = true;  --使⽤动态分区时,设置为ture。
de = nonstrict;  --动态分区模式,默认值:strict,表⽰必须指定⼀个分区为静态分区;nonstrict模式表⽰允许所有的分区字段都可以使⽤动态分区。⼀般需要设置为nonstrict。ax.dynamic.partitions.pernode =10;  --在每个执⾏MR的节点上,最多可以创建多少个动态分区,默认值:100。
ax.dynamic.partitions =1000;  --在所有执⾏MR的节点上,最多⼀共可以创建多少个动态分区,默认值:1000。
ax.created.files = 100000;  --整个MR Job中最多可以创建多少个HDFS⽂件,默认值:100000。
on.empty.partition = false;  --当有空分区产⽣时,是否抛出异常,默认值:false。
  Hive⽂件产⽣⼤量⼩⽂件的原因:
    ⼀是⽂件本⾝的原因:⼩⽂件多,以及⽂件的⼤⼩;
    ⼆是使⽤动态分区,可能会导致产⽣⼤量分区,从⽽产⽣很多⼩⽂件,也会导致产⽣很多Mapper;
    三是Reduce数量较多,Hive SQL输出⽂件的数量和Reduce的个数是⼀样的。
  ⼩⽂件带来的影响:
    ⽂件的数量和⼤⼩决定Mapper任务的数量,⼩⽂件越多,Mapper任务越多,每⼀个Mapper都会启动⼀个JVM来运⾏,所以这些任务的初始化和执⾏会花费⼤量的资源,严重影响性能。
    在NameNode中每个⽂件⼤约占150字节,⼩⽂件多,会严重影响NameNode性能。
  解决⼩⽂件问题:
    如果动态分区数量不可预测,最好不⽤。如果⽤,最好使⽤distributed by分区字段,这样会对字段进⾏⼀个hash操作,把相同的分区给同⼀个Reduce处理;
    减少Reduce数量;
    进⾏以⼀些参数调整。
控制Mapper的数量:
  决定Mapper的数量的因素有:输⼊⽂件的个数,输⼊⽂件的⼤⼩、集设置的⽂件块⼤⼩。
    例如:输⼊⽬录下有1个800M的⽂件,hadoop会将⽂件分成7个⽂件(6*128M + 1*32M),从⽽产⽣7个Mapper数;
    例如:输⼊⽬录下有5个⽂件,分别为:15M、20M、50M、100M、150M,那么hadoop会分隔成6个⽂件(15M、20M、50M、100M、128M、22M),从⽽产⽣6个Mapper。
  可以通过设置如下参数,让Map在执⾏之前合并⼩⽂件,从⽽减少Mapper数量:
set mapred.max.split.size=100000000;   -- 决定每个map处理的最⼤的⽂件⼤⼩,单位为B
set mapred.min.split.de=100000000;   -- 节点中可以处理的最⼩的⽂件⼤⼩
set mapred.min.split.size.per.rack=100000000;   -- 机架中可以处理的最⼩的⽂件⼤⼩
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;  ---实现map中的数据合并需要设置下⾯的参数,集默认就是这个格式
  控制Mapper的整体原则:
    ⼤数据量要利⽤合适的map数,单个map要处理合适的数据量;
    map占⽤资源要合并⼩⽂件,map不⾜要把⼤⽂件拆成⼩⽂件。
控制Reduce的数量:
  Reduce的个数会极⼤影响任务的执⾏效率
Hive⾃⼰确定reduce数
    不指定Reduce的个数的情况下,Hive会猜测确定⼀个Reduce个数,由下⾯两个参数决定:
    1、ducers.ducer(每个reduce任务处理的数据量,默认为1000^3=1G)
    2、ducers.max(每个任务最⼤的reduce数,默认为999)
    Reduce的个数N=min(参数2,输⼊总数据量/参数1),例如:如果Reduce的输⼊(map的输出)总⼤⼩不超过1G,那么只有⼀个Reduce任务。
⼿动调整reduce数
    Hive官⽹:
In order to change the average load for a reducer (in bytes): educers.ducer=<number>
In order to limit the maximum number of reducers: educers.max=<number>
In order to set a constant number of reducers: set duces=<number>
  Notes:动态分区采坑
    在使⽤动态分区的时候,如果已知数据会分成n个分区,SQL运⾏的时候创建了m个Mapper,则这个SQL产⽣m * n个⽂件。如果这个数值⼤于设置的创建⽂件的总数(ax.created.files),默认值100000个,就会出现异常。
    在未知动态分区数时,可以使⽤distribute by 分区字段,将分区字段内容相同的数据放到同⼀个reduce,当然也可以使⽤distribute by rand()将数据随记分配给reduce,这样可以使每个reduce处理的数据⼤体相同。
和map⼀样,启动和初始化reduce会消耗时间和资源,有多少reduce就会产⽣多少个⽂件
以下情况下,会只有⼀个reduce:
没有group by的汇总,如把select dt,count(1) from test where dt = '2019-12-12' group by dt;,写成select count(1) from test where dt = '2019-12-12';
⽤了order by;
有笛卡尔积;
  控制Reduce的整体原则:
    使⼤数据量利⽤合适的reduce数;
    使单个reduce任务处理合适的数据量。