Hive 基于MR引擎 map和reduce数的参数控制原理与调优经验

1.概述

主要对基于MR的map数和reduce数测试与调优

2.数据准备

(1)表信息

本次测试的表和sql都是使用的TPC-DS,表文件存储格式为text

表名

是否压缩

总数

占用空间

文件数

date_dim

73049

9.8 M

1

item

48000

12.9 M

1

store

118

30.5 K

1

store_sales

23039641872

3109G

8000

store_sales_compress

23039641872

825.3 G

3515

 store_sales事实大表的数据块分布

单个文件占用空间

380-400M

400M以上

文件数

7927

73

store_sales的表结构:

# 查看表的结构

show create table store_sales;
结果如下:
+----------------------------------------------------+
| createtab_stmt |
+----------------------------------------------------+
| CREATE EXTERNAL TABLE `store_sales`( |
| `ss_sold_date_sk` int, |
| `ss_sold_time_sk` int, |
| `ss_item_sk` int, |
| `ss_customer_sk` int, |
| `ss_cdemo_sk` int, |
| `ss_hdemo_sk` int, |
| `ss_addr_sk` int, |
| `ss_store_sk` int, |
| `ss_promo_sk` int, |
| `ss_ticket_number` bigint, |
| `ss_quantity` int, |
| `ss_wholesale_cost` float, |
| `ss_list_price` float, |
| `ss_sales_price` float, |
| `ss_ext_discount_amt` float, |
| `ss_ext_sales_price` float, |
| `ss_ext_wholesale_cost` float, |
| `ss_ext_list_price` float, |
| `ss_ext_tax` float, |
| `ss_coupon_amt` float, |
| `ss_net_paid` float, |
| `ss_net_paid_inc_tax` float, |
| `ss_net_profit` float) |
| ROW FORMAT SERDE |
| 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe' |
| WITH SERDEPROPERTIES ( |
| 'field.delim'='|', |
| 'serialization.format'='|') |
| STORED AS INPUTFORMAT |
| 'org.apache.hadoop.mapred.TextInputFormat' |
| OUTPUTFORMAT |
| 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat' |
| LOCATION |
| 'hdfs://server1:8020/tmp/tpcds-generate/8000/store_sales' |
| TBLPROPERTIES ( |
| 'bucketing_version'='2', |
| 'transient_lastDdlTime'='1598978311') |
+----------------------------------------------------+

(2)SQL CPU密集型语句

with v1 as (
select i_category, i_brand,
s_store_name, s_company_name,
d_year, d_moy,
sum(ss_sales_price) sum_sales,
avg(sum(ss_sales_price)) over
(partition by i_category, i_brand,
s_store_name, s_company_name, d_year)
avg_monthly_sales,
rank() over
(partition by i_category, i_brand,
s_store_name, s_company_name
order by d_year, d_moy) rn
from item, store_sales, date_dim, store
where ss_item_sk = i_item_sk and
ss_sold_date_sk = d_date_sk and
ss_store_sk = s_store_sk and
(
d_year = 2000 or
( d_year = 2000-1 and d_moy =12) or
( d_year = 2000+1 and d_moy =1)
)
group by i_category, i_brand,
s_store_name, s_company_name,
d_year, d_moy),
v2 as(
select v1.i_category, v1.i_brand
,v1.d_year
,v1.avg_monthly_sales
,v1.sum_sales, v1_lag.sum_sales psum, v1_lead.sum_sales nsum
from v1, v1 v1_lag, v1 v1_lead
where v1.i_category = v1_lag.i_category and
v1.i_category = v1_lead.i_category and
v1.i_brand = v1_lag.i_brand and
v1.i_brand = v1_lead.i_brand and
v1.s_store_name = v1_lag.s_store_name and
v1.s_store_name = v1_lead.s_store_name and
v1.s_company_name = v1_lag.s_company_name and
v1.s_company_name = v1_lead.s_company_name and
v1.rn = v1_lag.rn + 1 and
v1.rn = v1_lead.rn - 1)
select *
from v2
where d_year = 2000 and
avg_monthly_sales > 0 and
case when avg_monthly_sales > 0 then abs(sum_sales - avg_monthly_sales) / avg_monthly_sales else null end > 0.1
order by sum_sales - avg_monthly_sales, d_year
limit 100;

 

3.map数的控制

3.1 map数控制测试

Hive中来控制map数量的参数不是Hive本身的参数,而是MapReduce的参数,但是可以通过在Hive中使用set的形式来使用。影响map个数的hive参数如下表:

参数

默认值

说明

mapreduce.input.fileinputformat.split.maxsize

256000000

每个Map的最大输入

mapreduce.input.fileinputformat.split.minsize

1

每个Map的最小输入

mapred.map.task

2

Task数量

hive.input.format

org.apache.hadoop.hive.ql.io. CombineHiveInputFormat

输出格式

dfs.block.size

134217728

默认的block块大小

 说明:dfs.block.size参数不能通过Hive的set语句来设置,只能通过修改HDFS的参数来设置。

3.1.1 HiveInputFormat

当输入类型为HiveInputFormat时,map数量由以下参数控制,且剩余的小文件不会合并:

参数

默认值

说明

mapreduce.input.fileinputformat.split.minsize

1

每个Map的最小输入

mapred.map.task

2

Task数量

dfs.block.size

134217728

默认的block块大小

文件的分割大小满足下面的公式:

splitSize= max{ mapreduce.input.fileinputformat.split.minsize ,min{ dfs.block.size , 表大小 / mapred.map.task } }

测试1:

参数设置:
mapred.map.tasks=2;
mapreduce.input.fileinputformat.split.minsize=1;

结果打印:
Hadoop job information for Stage-4: number of mappers : 29930 ; number of reducers :1009

共有29930个map数

根据公式可以计算出来,文件分割大小为dfs.block.size的值,128M。

store_sales表总共有8000个文件,数据量分布在380-410M之间。

例子:

一个400M的文件,理论上根据128M分割,会分割成4个文件。(128M,128M,128M,16M)

一个350M的文件,理论上根据128M分割,会分割成3个文件。(128M,128M,94M)

所以map数应该在3*8000 ~ 4*8000之间。结果值29930满足上述公式。

测试2:

参数设置:
mapred.map.tasks=2;
mapreduce.input.fileinputformat.split.minsize=256000000;

结果打印:
Hadoop job information for Stage-4: number of mappers : 16000 ; number of reducers :1009

共有16000个map数

根据公式可以计算出来,文件分割大小为mapreduce.input.fileinputformat.split.minsize的值为244M。

每个文件都被分成两个文件,所以map数为16000。

测试3:

参数设置:
mapred.map.tasks=2;
mapreduce.input.fileinputformat.split.minsize= 512000000;

结果打印:
Hadoop job information for Stage-4: number of mappers : 8000; number of reducers :1009

总共有8000个map数

根据公式可以计算出来,文件分割大小为mapreduce.input.fileinputformat.split.minsize的值为488M。

每个文件都被分成一个文件,所以map数为8000。

测试4:

参数设置:
mapred.map.tasks=2;
mapreduce.input.fileinputformat.split.minsize= 1024000000;

结果打印:
Hadoop job information for Stage-4: number of mappers : 8000 ; number of reducers :1009

总共有8000个map数

根据公式可以计算出来,文件分割大小为mapreduce.input.fileinputformat.split.minsize的值为488M。

每个文件都被分成一个文件,所以map数为8000。

3.1.2 CombineHiveInputFormat

当输入类型为CombineHiveInputFormat时,map数量由以下参数控制,剩余的小文件会合并:

参数

默认值

说明

mapreduce.input.fileinputformat.split.maxsize

256000000

每个Map的最大输入

 测试1:

参数设置:
mapreduce.input.fileinputformat.split.maxsize=256000000;

结果打印:
Hadoop job information for Stage-4: number of mappers : 12001; number of reducers :1009

总共有12001个map数

由于CombineHiveInputFormat,会对小文件进行合并,所以需要根据数据的总量去计算map数,3000 * 1024 / 12000≈256000000

测试2:

参数设置:
mapreduce.input.fileinputformat.split.maxsize=128000000;

结果打印:
Hadoop job information for Stage-4: number of mappers : 24001; number of reducers :1009

总共有24001个map数

测试3:

参数设置:
mapreduce.input.fileinputformat.split.maxsize=512000000;

结果打印:
Hadoop job information for Stage-4: number of mappers : 6001; number of reducers :1009

总共有6001个map数

测试4:

参数设置:
mapreduce.input.fileinputformat.split.maxsize=1024000000;

结果打印:
Hadoop job information for Stage-4: number of mappers : 3001; number of reducers :1009

总共有3001个map数

3.1.3 Text格式文件压缩

压缩相关参数

参数

默认值

说明

io.compression.codecs

org.apache.hadoop.io.compress.GzipCodec,

org.apache.hadoop.io.compress.DefaultCodec,

org.apache.hadoop.io.compress.SnappyCodec

Hive配置可用的压缩算法

hive.exec.compress.output

false

开启压缩

mapreduce.output.fileoutputformat.compress.codec

org.apache.hadoop.io.compress.DefaultCodec

使用的压缩算法

测试使用store_sales_compress表,Text格式,压缩格式为DefaultCodec,文件都是.deflate结尾的。DefaultCodec不支持文件切分,每个文件大小分布在280M~340M之间

表名

是否压缩

总数

占用空间

文件数

store_sales_compress

23039641872

825.3 G

3515

测试1:

参数设置:
mapreduce.input.fileinputformat.split.maxsize=512000000;

结果打印:
Hadoop job information for Stage-4: number of mappers : 3515; number of reducers :1009

总共有3515个map数

测试2:

参数设置:
mapreduce.input.fileinputformat.split.maxsize=256000000;

结果打印:
Hadoop job information for Stage-4: number of mappers : 3515; number of reducers :1009

总共有3515个map数

因为文件存储使用了DefaultCodec压缩,且DefaultCodec压缩不支持文件切分,所以我们设置参数为256000000时没有生效。

测试3:

参数设置:
mapreduce.input.fileinputformat.split.maxsize=128000000;

结果打印:
Hadoop job information for Stage-4: number of mappers : 3515; number of reducers :1009

总共有3515个map数

因为文件存储使用了DefaultCodec压缩,且DefaultCodec压缩不支持文件切分,所以我们设置参数为128000000时没有生效。

3.2 map数控制结果

3.2.1 HiveInputFormat

mapreduce.input.fileinputformat.split.minsize值

Map数

1

29930    

256000000

16000

512000000

8000

1024000000

8000


3.2.2 CombineHiveInputFormat

mapreduce.input.fileinputformat.split. maxsize值

Map数

256000000

12001    

128000000

24001

512000000

6001

1024000000

3001

3.2.3 Text格式文件压缩

mapreduce.input.fileinputformat.split. maxsiz值

Map数

512000000

3515       

256000000

3515

128000000

3515

4.reduce数的控制

4.1 影响reduce个数的参数

参数

默认值

说明

mapred.reduce.tasks

-1

指定reduce的个数

hive.exec.reducers.bytes.per.reducer

67108864

每个reduce的数据处理量

hive.exec.reducers.max

1009

reduce的最大个数

reduce的个数满足下面的公式:

reduce=min(hive.exec.reducers.max, map input数据大小/hive.exec.reducers.bytes.per.reducer)

reduce的个数控制相对于map就要简单很多,并且可以精确地来控制reduce的个数。

(1)mapred.reduce.tasks

可以通过修改mapred.reduce.tasks的值来精确控制reduce的个数。默认情况下不设置,除非对于某个特定的SQL语句可以单独设置,但是功能上没有hive.exec.reducers.max来的方便。

其中,每个reduce处理的数据为(总数据量 /设置的reduce个数)。

测试1:

参数设置:
set mapred.reduce.tasks=200;

结果打印:
Hadoop job information for Stage-4: number of mappers : 12001; number of reducers :200

总共有200个reduce,从上述的1009个变成200个。

(2)hive.exec.reducers.bytes.per.reducer

测试1:

参数设置:
set hive.exec.reducers.bytes.per.reducer = 67108864;

结果打印:
Hadoop job information for Stage-4: number of mappers : 12001; number of reducers :1009

共有1009个reduce数

根据公式可以计算出:

3109 * 1024 / (67108864/ 1024 /1024 ) = 49744 > 1009,所以reduce个数为1009

测试2:

参数设置:
set hive.exec.reducers.bytes.per.reducer = 4096000000;

结果打印:
Hadoop job information for Stage-4: number of mappers : 12001; number of reducers :816

共有816个reduce数

根据公式可以计算出:

3109 * 1024 / (4096000000 / 1024 /1024 ) = 815 < 1009 ,根据结果需要取815值。算出来的值也基本等于上面的816

 

5.调优流程

(1)map

基于MR,先判断文件是否压缩,且压缩文件是否支持切分,再判断是hive.input.format的实现类。然后使用相对应的参数进行map数调优。

(2)reduce

需要根据集群的资源以及map端实际的输出数据量来设置reduce数。

 

6.总结

(1)map

  • 当使用压缩时,如果压缩文件不可切分,那么久不能通过修改参数来改动map数。所以在选择压缩算法时,需要考虑该压缩算法是否支持文件切分。

  • 在MR作为引擎的情况下,推荐使用CombineHiveInputFormat,而不是HiveInputFormat

  • 需要通过测试来得到性能好的map数。不是越多越好,也不是越少越好

(2)reduce

  • 推荐reduce数为集群能启动的最大container数的80%,或者小于这个数。

  • mapred.reduce.tasks这个参数一般不推荐使用。

猜你喜欢

转载自blog.csdn.net/qq_35260875/article/details/110181866