写点什么

大数据培训 Hive 如何控制 map 个数与性能调优参数

作者:@零度
  • 2022 年 4 月 12 日
  • 本文字数:8265 字

    阅读完需:约 27 分钟

 以下文章来源于涤生大数据

1 Hive 有哪些参数,如何查看这些参数

Hive 自带的配置属性列表封装在 HiveConfJava 类中,因此请参阅该 HiveConf.java 文件以获取 Hive 版本中可用的配置属性的完整列表。具体可以下载 hive.src 通过 eclipse 查看。全部属性有上千个吧,一般 Hive 的自带属性都是以 hive.开头的,每个属性且自带详细的描述信息,其次 Hive 官网也有,但是属性不是特别全。



Hive 除了自身带了一些配置属性,因为其底层使用的是 hadoop(HDFS,MR,YARN),所以有些 HADOOP 的配置属性 Hive 也可以使用,进行配置,但是有些则使用不了。比如 mapred.max.split.size 就属于 MR 的参数,但是 hive 可以使用。

2 map 个数的控制参数与性能调优

很显然,对于这个控制每个 map 的 split 输入大小的参数,不是 hive 自带的参数,而是 MR 提供的参数,但是 Hive 可以通过 set 的形式配置使用,而且对于调优有很大的作用。但是这个参数实际上要配合 HDFS 的 blocksize 一起使用。下面以我们公司开发环境的默认配置参数_大数据培训

-- 每个 Map 最大输入大小,

hive> set mapred.max.split.size;

mapred.max.split.size=256000000 这也是官方默认值

-- 每个 Map 最小输入大小

hive> set mapred.min.split.size;

mapred.min.split.size=10000000 这也是官方默认值

hive> set dfs.block.size;

dfs.block.size=134217728

#我们集群默认 hdfs 的 block 块大小是 128Mb,但注意这个参数通过 hive 设置更改实际没有用的,只能 hdfs 设置。

2.1 数据准备,两张表

如下进行两张表 join,其中每张表的大小,hdfs 上存储的文件总个数,以及每个文件的大小。

1.大表总共 158749566 行,文件总大小 4.4G,存储个数 22 个文件,每个大小 200Mb 左右。

2.小表总共 1979375 行,文件大小 50.7Mb,存储个数 2 个文件,大小 50Mb 以内。

[finance@hadoop-client13-prd ~]$ hadoop fs -du -h hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d

206.7 M hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d/000000_0.deflate

.....省略.................

hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d/000021_0.deflate

---------------------------------------------------------------------------------------

[finance@hadoop-client13-prd ~]$ hadoop fs -du -h hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/t_fgeics_company_liquidation_d_tmp

36.4 M hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/t_fgeics_company_liquidation_d_tmp/000000_0.deflate

14.3 M hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/t_fgeics_company_liquidation_d_tmp/000001_0.deflate

2.2 两个表进行关联,其中小表在前,大表在后

2.2.1 如下,运行如下代码,实现两个表进行关联。

set mapred.max.split.size=134217728;

set mapred.min.split.size=134217728;

drop table IF EXISTS fdm_tmp.company_liquidation_fgeics_company_ar_d_tmp;

create table fdm_tmp.company_liquidation_fgeics_company_ar_d_tmp

as

select

a.id

,a.entid

,a.ancheyear

,b.liqmen

,b.ligprincipal

,a.regno

,a.tel

,a.postalcode

,a.dom

,a.email

,a.busst

,a.empnum

,a.name

,a.updated

,b.etl_time

from fdm_tmp.t_fgeics_company_liquidation_d_tmp b

right join fdm_tmp.company_liquidation_fgeics_company_ar_d a

on b.entid = a.entid;

Hadoop job information for Stage-1: number of mappers: 24; number of reducers: 17

结果分析:hive 启动了 24 个 map 函数,17 个 reduce 函数。在 hadoop 中,一般默认的 split 切片小于等于 blocksize(128Mb),如果是小文件的话(未进行小文件的合并)则每个小文件启动一个 map 函数。而实际在 hive 中,并不是 split 的大小要小于等于 blocksize,而是可以远大于 blocksize。比如这里,4.4G 文件表,按 128Mb 切片算的话,至少实际需要 35 个 map,而实际只需要 24 个,平均每个 map 处理了 187Mb 的文件。这是为什么呢?此外这里明明设置了 set mapred.max.split.size=134217728,每个 map 最大 split 块是 128Mb,而实际为什么参数没有用呢?网上有很多关于这方面的文章,但是几乎都是转载抄袭,没有任何深入理解,或者深入剖析决定 map 个数的原因。

3 案例演示决定 map 个数的因素

其实决定 map 个数的因素有很多,比如文件是否压缩,压缩的后的文件是否支持切分,比如文件默认的 inputfort 格式,不同实现类的 split 算法也不同,那么 map 的个数调优方式也不同,下面按分类详细说明 hive 中决定 map 个数的因素与常见 map 调优的使用。

首先分类:处理的文件是否压缩,且压缩算法是否支持文件的切分

如下我们公司,对于 hive 关于压缩的配置,使用了压缩,且使用的是默认的压缩算法是 deflate 方法。

hive> set io.compression.codecs; --配置了哪些压缩算法

io.compression.codecs=org.apache.hadoop.io.compress.GzipCodec,org.apache.hadoop.io.compress.DefaultCodec,com.hadoop.compression.lzo.LzoCodec,com.hadoop.compression.lzo.LzopCodec,org.apache.hadoop.io.compress.BZip2Codec

hive> set hive.exec.compress.output;

hive.exec.compress.output=true --是否开启压缩

hive> set mapreduce.output.fileoutputformat.compress.codec; --使用的压缩算法

mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.DefaultCodec

我们知道 hive 中有些压缩算法是不支持文件切分的,如下我们使用的默认的 deflate 算法,就不支持文件切分。



3.1 文件使用了压缩,且压缩算法不支持文件切分

------------------------使用不同参数执行上面代码产生的 map 个数---------------------------------

--1.使用系统配置的默认值

set mapred.max.split.size = 256000000; --

set mapred.min.split.size = 256000000;

Hadoop job information for Stage-1: number of mappers: 24; number of reducers: 17

--2.降低系统默认值

set mapred.max.split.size=134217728;

set mapred.min.split.size=134217728;

Hadoop job information for Stage-1: number of mappers: 24; number of reducers: 17

--3.调高系统默认值

set mapred.max.split.size=500000000;

set mapred.min.split.size=256000000;

Hadoop job information for Stage-1: number of mappers: 9; number of reducers: 17

--4.调高系统默认值

set mapred.max.split.size=1024000000;

set mapred.min.split.size=1024000000;

Hadoop job information for Stage-1: number of mappers:6 ; number of reducers: 17

如上我们使用不同的参数配置,来运行上面同一段代码,看系统产生的 map 个数,细心的人会发现,当我们使用默认值是产生了 24 个 map,平均每个 map 处理了 187Mb 文件,但当我们调低

set mapred.max.split.size=134217728 时(每个 map 最多处理 128Mb),相应的 map 个数并没有增加,这是为什么呢?

关于这个问题就要说到决定 map 个数的首要因素:文件是否启动压缩,且压缩算法是否支持文件切分了。因为这里文件存储使用默认的 deflate 算法,不支持文件切分,所以设置的参数 split.size=134217728 没有生效。因为每个 map 处理的 splitsize 实际上要大于等于每个文件存储的大小。这里每个文件存储的大小 200Mb 左右,所以每个 map 处理的最小尺寸要大于 200Mb。

而当我们将 set mapred.max.split.size=102400000 设置的很大时,为什么又可以控制 map 个数了呢?因为 deflate 压缩算法虽然不支持文件切分,但是可以进行文件合并哇。从 hive0.5 开始就默认 map 前进行小文件合并了。如下,我们公司使用的也是默认的开启 map 前文件合并。但是注意即使这里支持文件合并,也是基于文件块的整个文件块合并,而不是基于 blocksize 的 block 合并。

hive> set hive.input.format; --hive0.5 开始的默认值,这个值会影响 map 个数的控制

hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat

尖叫提示 1:

通过上面分析总结,当 hive 需要处理的文件是压缩,且压缩算法不支持文件切分的时候,决定 map 个数的因素主要是文件块实际存储的大小,如果文件块本身很大,比如 500Mb 左右,那么每个 map 处理的 splitsize 至少要是 500Mb 左右。这个时候我们不能人为通过参数降低每个 map 的 splitsize 来增加 map 个数,只能通过增加 splitsize,减少 map 个数。

但是一般经验来说,每个 map 处理的 splitsize 最好是 128Mb(等于 blocksize),这样效率最高。所以这个时候如果我们想增加 map 个数,只能通过临时表或者 insert ...select 的形式,通过参数配置将文件块重新存储成较小的文件块,然后再进行处理。反之,如果文件块本身很小,那么我们可以通过增加 splitsize 来减少 map,进而调优提高程序的运行效率。

尖叫总结 1:

如果 hive 处理的文件是压缩模式,且压缩模式不支持文件切分,那么这个时候我们只能通过控制参数来减少 map 个数,而不能通过配置参数来增加 map 个数,所以 Hive 对于压缩不可切分文件的调优有限。可以首先通过 hadoop fs -du -s -h 命令查看文件的存储大小结果,然后根据实际进行调优。常用的配置参数如下:

set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; --hive0.5 开始就是默认值,执行 map 前进行小文件合并

----------------------------------------------------------------------

set mapred.max.split.size=256000000

set mapred.min.split.size=10000000

set mapred.min.split.size.per.node=8000000 --每个节点处理的最小 split

set mapred.min.split.size.per.rack=8000000 --每个机架处理的最小 slit.

------------------------------------------------------------------------

1.注意一般来说这四个参数的配置结果大小要满足如下关系。

max.split.size >= min.split.size >= min.size.per.node >= min.size.per.node

2.这四个参数的作用优先级分别如下

max.split.size <= min.split.size <= min.size.per.node <= min.size.per.node

比如如下,同样上面的代码,我们将其参数设置如下,发现只启动了 12 个 map,故 max.split.size 没有起作用。

当四个参数设置矛盾时,系统会自动以优先级最高的参数为准,进行计算

set mapred.max.split.size=300000000;

set mapred.min.split.size.per.node=300000000;

set mapred.min.split.size.per.rack=300000000;

Hadoop job information for Stage-1: number of mappers: 12; number of reducers: 17

3.注意这四个参数可以选择性设置,可以选择性设置大小或者使用默认值,但仍遵循前两条规则。

3.2 文件未使用压缩,或压缩算法支持文件切分

同样是上面那个 4.4g 文件,我们这个时候让其为非压缩模式,发现这个时候文件总大小为 23.4G,存储为 22 个文件,平均每个文件大小都在 1.1G 左右。所以压缩有时候是个好东西。如下我们所有非压缩的性能测试基于此文件。

[finance]$ hadoop fs -count hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d

1 22 25154158871 hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d

-------------------------------------------------------------------------------------------------------------------------

[finance]$ hadoop fs -du -s -h hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d

23.4 G hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d

-------------------------------------------------------------------------------------------------------------------------

[finance]$ hadoop fs -du -h hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d

1.1 G hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d/000000_0

1.1 G hdfs://suninghadoop2/user/finance/hive/warehouse/fdm_tmp.db/company_liquidation_fgeics_company_ar_d/000001_0

...............................

3.2.1.若这时 set hive.input.format 为 HiveInputFormat

hive> set hive.input.format; --从 hive0.5 就默认是 CombineHiveInputFormat,所以这个用的不多

hive.input.format=org.apache.hadoop.hive.ql.io.HiveInputFormat;

如果这时 set hive.input.format 为 HiveInputFormat,这个时候有以下三个属性值来确定 InputSplit 的个数:

set mapred.map.tasks=2 --我们公司使用的是默认 2

set mapred.max.split.size=256000000 --我们公司默认值

set mapred.min.split.size=10000000 ---我们公司默认值

set dfs.block.size=134217728 --128Mb

----------------------------------------------------------------------------------------

1. goalSize:该值由 totalSize/numSplits totlasize 文件块大小,numslplits=mapred.map.tasks=2

2. minSize:由配置参数 mapred.min.split.size(或者新版本的 mapreduce.input.fileinputformat.split.minsize)mapred.min.split.size=10000000

决定的 InputFormat 的最小长度,默认为 1,我们公司默认值是

3.blockSize:HDFS 中的文件存储块 block 的大小,默认为 128MB。

这三个参数决定一个 InputFormat 分片的最终的长度,计算方法如下:

splitSize = max{minSize,min{goalSize,blockSize}}

尖叫总结 2:

当 hive 处理的文件是非压缩或者压缩可切分,且 hive.input.format 为 HiveInputFormat 时,这个时候决定 map 个数的参数主要是 splitSize = max{minSize,min{goalSize,blockSize}} ,只有这个时候一般 map 的 splitsize 小于等于 blocksize(128Mb)。但其实这种方式现在企业实际开发中已经使用的很少了。

3.2.2.若 hive.input.format 为默认 CombineHiveInputFormat

1.如下,使用公司默认的 map 函数 split 参数,发现未压缩的 23.4g 的文件(22 个)这里共使用了 112 个 map 函数,符合参数的设置结果 set mapred.max.split.size=256000000 ; 23.4*1024/112=187Mb<256000000。

--使用默认配置参数,实现对非压缩文件的操作

set mapred.max.split.size=256000000 ;

set mapred.min.split.size=10000000;

drop table IF EXISTS fdm_tmp.company_liquidation_fgeics_company_ar_d_tmp;

create table fdm_tmp.company_liquidation_fgeics_company_ar_d_tmp

as

select

a.id

,a.entid

,a.ancheyear

,b.liqmen

,b.ligprincipal

,a.regno

,a.tel

,a.postalcode

,a.dom

,a.email

,a.busst

,a.empnum

,a.name

,a.updated

,b.etl_time

from fdm_tmp.t_fgeics_company_liquidation_d_tmp b

right join fdm_tmp.company_liquidation_fgeics_company_ar_d a

on b.entid = a.entid;

Hadoop job information for Stage-1: number of mappers: 112; number of reducers: 85

Time taken: 152.679 seconds

2.如下,将上面默认的参数对应调小,运行同样上面的代码,看 map 数是否有增加?很显然,我们通过设置 max.split.size 的值实现了增加 map 个数的功能。这里 map 的个数由 122 个数变成了 199 个,平均每个 map 处理数据 120Mb 左右。但是运行时间却变慢了很多,时间由 153s 变成了 243s。所以 map 的 split 大小并不是要接近 blocksize 才高效,这主要跟集群的性能配置有关。

--将 map 的 split 参数最大值设置为 128Mb.

set mapred.max.split.size=134217728 ;

set mapred.min.split.size=10000000;

Hadoop job information for Stage-1: number of mappers: 199; number of reducers: 85

Time taken: 243.038 seconds

3.如下,将上面的默认参数增加,运行同样的代码,结果虽然我们将 maxsplitsize 设置的特别大,但是对应 map 的个数并没有对应的成倍减少,如果按最大值算应该在 20 多个 map,而实际不是这样。这说明,光设置最大值是没有用的,这只是一个峰值,还有对应的设置最小值。

--只将 max.split.size 设置的特别大,min.split.size 还是 10Mb 左右。

set mapred.max.split.size=1024000000;

set mapred.min.split.size= 10000000;

Hadoop job information for Stage-1: number of mappers: 106; number of reducers: 85

4.map 的多个参数配合使用,精确控制 map 的个数

--1.只将 max.split.size 设置的特别大,且将 min.split.size 使用默认值,发现 map 个数没有成倍减少。

set mapred.max.split.size=1024000000;

set mapred.min.split.size=10000000;

Hadoop job information for Stage-1: number of mappers: 106; number of reducers: 85

------------------------------------------------------------------------------------

--2.同时将 max.split.size 设置的特别大,且将 min.split.size 同时设置很大为 256Mb 左右

但是发现 map 的个数并没有减少,还是和上面一样,这说明控制 map 的个数还有别的因素

set mapred.max.split.size=1024000000;

set mapred.min.split.size=256000000;

Hadoop job information for Stage-1: number of mappers: 106; number of reducers: 85

------------------------------------------------------------------------------------

---3.配合 min.split.size.per.node 使用,发现 map 个数仍然没有减少

set mapred.max.split.size=1024000000;

set mapred.min.split.size= 256000000;

set mapred.min.split.size.per.node=256000000;--默认值是 800000

set mapred.min.split.size.per.rack=800000;---默认值

--------------------------------------------------------------------------------------

---4.配合 min.split.size.per.rack 使用,map 个数精准减少了,每个 map 处理的数据在 256 和 1024 之间

Hadoop job information for Stage-1: number of mappers: 106; number of reducers: 85

set mapred.max.split.size=1024000000;

set mapred.min.split.size= 256000000;

set mapred.min.split.size.per.node=256000000;

set mapred.min.split.size.per.rack=256000000;

Hadoop job information for Stage-1: number of mappers: 88; number of reducers: 85

尖叫总结 3:

如果 Hive 处理的的文件为非压缩格式或者压缩可切分,且 inputFormat 为 CombineHiveInputFormat 时,则控制 map 个数是由以下四个参数起作用,关于这四个参数作用优先级与使用注意事项请参考如下。

mapred.min.split.size 或者 mapreduce.input.fileinputformat.split.minsize。

mapred.max.split.size 或者 mapreduce.input.fileinputformat.split.maxsize。

mapred.min.split.size.per.rack 或者 mapreduce.input.fileinputformat.split.minsize.per.rack。

mapred.min.split.size.per.node 或者 mapreduce.input.fileinputformat.split.minsize.per.node。

set hive.input.format = org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; --hive0.5 开始就是默认值,执行 map 前进行小文件合并

----------------------------------------------------------------------

set mapred.max.split.size=256000000 --公司集群默认值

set mapred.min.split.size=10000000 --公司集群默认值

set mapred.min.split.size.per.node=8000000 --每个节点处理的最小 split

set mapred.min.split.size.per.rack=8000000 --每个机架处理的最小 slit.

------------------------------------------------------------------------

1.注意一般来说这四个参数的配置结果大小要满足如下关系。

max.split.size >= min.split.size >= min.size.per.node >= min.size.per.node

2.这四个参数的作用优先级分别如下

max.split.size <= min.split.size <= min.size.per.node <= min.size.per.node

比如如下,同样上面的代码,我们将其参数设置如下,发现只启动了 12 个 map,故 max.split.size 没有起作用。

当四个参数设置矛盾时,系统会自动以优先级最高的参数为准,进行计算

set mapred.max.split.size=300000000;

set mapred.min.split.size.per.node=300000000;

set mapred.min.split.size.per.rack=300000000;

Hadoop job information for Stage-1: number of mappers: 12; number of reducers: 17

3.注意这四个参数可以选择性设置,可以选择性设置大小或者使用默认值,但仍遵循前两条规则。

所以如果对于 Hive 调优,想通过控制 map 个数进行调优,首先确定集群是否启动了压缩,且压缩的算法是否直接文件切分,然后再确定集群配置的默认的 hive.input.format 是什么实现类,不同实现类对于 split 的算法不同,当然控制 map 的参数也不同。所以对于控制 map 个数调优远远不是网上很多人说的那么简单。



用户头像

@零度

关注

关注尚硅谷,轻松学IT 2021.11.23 加入

IT培训 www.atguigu.com

评论

发布
暂无评论
大数据培训Hive如何控制map个数与性能调优参数_hive_@零度_InfoQ写作平台