Spark 大/小文件读取优化

问题描述

使用Spark写复杂SQL时,我们经常会遇到两个尴尬的情况:

  • 表里的单个文件都很大,而且因为record比较小,所以单个文件的record数量巨大。

  • 表里每个分区都有成百上千个小文件,单个文件可能只有几条记录

对于第一种情况,会导致我们没办法充分利用我们已有的核,所以速度很慢。

对于第二种情况,则会大量浪费调度时间。比如你有100万个文件,假设只有100个核,那么需要调度一万轮,每轮调度除了调度自身的消耗,还有很多额外的消耗。在没有shuffle的情况下,会导致写太多文件,本身就浪费性能,如果有shuffle,则对这么多map进行合并,本身也带来额外消耗。所以最佳办法是在读取的时候就能生成较少的分区,从而减少开销。

大文件优化读取优化

大文件优化读取需要关注两个参数:

spark.files.maxPartitionBytes=   默认128m
parquet.block.size= 默认128m

第一个参数是针对session有效的,也就是因为这你在读的时候设置就会立刻生效。在没有第二个参数配合的情况下,就已经能够增加分区数了,缺点是,分区里的数据可能不会很均匀,因为均匀程度也会受到第二个参数的影响。

然而,第二个参数需要写入的时候就配置上。所以大家有条件可以设置下,方便遇到文件较大,然后单条记录又很小的情况下,查询可以更灵活控制。

小文件读取优化

小文件读取首先有基础参数要设置(其中parquet已经是默认打开的),分别是针对parquet格式和ORC的。

spark.sql.hive.convertMetastoreParquet=true (默认已经为true)
spark.sql.hive.convertMetastoreOrc=true

只要是 Parquet 或者 ORC,无论是 Hive 表还是 datasource,默认都走 FileScan,都支持合并。所以大部分情况,这两个参数大家可以当做不存在。

接下来就是通过另外两个参数来控制怎么进行小文件合并了(多个文件合并成一个分区):

spark.files.maxPartitionBytes=   默认128m
spark.files.openCostInBytes=     默认4m

我们简单解释下这两个参数(注意他们的单位都是bytes):

  •  maxPartitionBytes参数控制一个分区最大多少。

  •  openCostInBytes控制当一个文件小于该阈值时,会继续扫描新的文件将其放到到一个分区

所以理论上你可以将openCostInBytes再设置大一点,减少分区读取。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值