判断SparkSQL中createOrReplaceTempView是行动算子还是转换算子

原因

今天在优化Scala编写的Spark脚本时,发现脚本中大量使用了createOrReplaceTempView()方法,此时恰好优化遇到了瓶颈。
运行期间发现,在while循环中每次用到临时表都需要读取一次,由于临时表的大小大概为40G,每次读取要话费3-4分钟,处理半年的数据就要花费几个小时,及其消耗性能。

寻找解决方案

进入IDEA去查看该方法的源码,如下:

def createOrReplaceTempView(viewName: String): Unit = withPlan {
    createTempViewCommand(viewName, replace = true, global = false)
  }

一开始是一直往下寻找,但到最后都没有发现到底它是个行动算子还是转换算子
后面再次往上溯源时发现原来一开始就已经说明了是个什么算子
先来看看一个普通的行动算子和转换算子:mapcollect

  def map[U : Encoder](func: T => U): Dataset[U] = withTypedPlan {
    MapElements[T, U](func, logicalPlan)
  }
def collect(): Array[T] = withAction("collect", queryExecution)(collectFromPlan)

这两个都是基于SparkSQL的调用,即基于DataSet的调用。
对于map函数,其中调用的withTypedPlan函数,对他的描述为:A convenient function to wrap a logical plan and produce a Dataset.
翻译之后为:包装逻辑计划并生成数据集的便捷功能。
对于collect函数,调用的withAction方法,描述为:Wrap a Dataset action to track the QueryExecution and time cost, then report to the user-registered callback functions.
翻译后为:包装一个 Dataset 操作以跟踪 QueryExecution 和时间成本,然后报告给用户注册的回调函数。
可以看出后者为行动算子,前者为转换算子,因为一个是生成DataSet,一个是返回Array[T]。
同样的,对于createOrReplaceTempView函数,调用的是withPlan方法,其描述为:A convenient function to wrap a logical plan and produce a DataFrame.
翻译后为:包装逻辑计划并生成 DataFrame 的便捷函数。
因此可以看出createOrReplaceTempView函数其实是一个转换算子,并不会有结果生成
也就是说,在Spark中,由于lazy机制,只有每次调用时才会产生计算,并且也一定会产生计算。

解决方案

由于每次调用都会读取,在循环当中每次都读取并写入的方式并不可取。因此我对其进行调整,改成了如下操作
spark.read.parquet("").cache().createOrReplaceTempView("")
在第一次读取时进行cache,由于需要用到180次,所以虽然内存会消耗更多,但是对于却会大大缩短运行时间。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值