createOrReplaceTempView原理以及效率优化之cache与persist

1. 前言

  在spark程序实际开发过程中遇到需要对文件内容做join操作,使用createOrReplaceTempView 方式将读取的文件创建临时表,然后通过 spark.sql()
方式利用sql语句做join操作,但是数据量稍微大点时候,就会导致join效率很慢。查询资料得知,这里有优化的空间,利用 cache() 或者 persist() 方法。

2. 原理

  createOrReplaceTempView是 transformation 算子,而transformation是lazy模式的,也就是spark不会立即计算结果,而只是简单地记住所有对数据集的转换操作逻辑,需要有action算子来触发spark应用程序,最简单的action算子:show()。例如:spark.sql("select *** from XXX ").createOrReplaceTempView(“tmp_test_table”).show()。
这样每次执行.show()算子时候,都需要先执行createOrReplaceTempView操作,导致效率很慢。肯有直接将读取出来的数据缓存起来,或者将createOrReplaceTempView之后的数据缓存到内存中。

缓存的方式有两种,具体使用不在此做赘述
1) cache()方法表示:使用非序列化的方式将RDD的数据全部尝试持久化到内存中,cache()只是一个transformtion,是lazy的,必须通过一个action触发,才能真正的将该RDD cache到内存中。
2)persist()方法表示:手动选择持久化级别,并使用指定的方式进行持久化。

3. 代码测试验证

数据量:math1.txt 5000行;sports1.txt 270行
机器:windows 16G内存

读取文件代码,参考:spark读写hdfs文件

不加缓存:耗时约8秒

//创建一个sparkSession对象
val conf = new SparkConf().setMaster("local[*]").setAppName("SparkHdfsOps")
    val sparkSession = SparkSession.builder()
      .config(conf)
      .getOrCreate()
//新建两个视图
println("创建视图 math_df_table")
math_df.createOrReplaceTempView("math_df_table")
println("创建视图 sports_df_table")
sports_df.createOrReplaceTempView("sports_df_table")
//作join操作
println("join结果如下: ")
val startStamp = new Date().getTime
val start = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startStamp)

sparkSession.sql("select a.name,a.age,a.skills,b.role,b.team from sports_df_table a left join math_df_table b on a.name=b.name").show(10)
sparkSession.sql("select count(*) from sports_df_table a left join math_df_table b " +
      "on a.name=b.name").show()

val endStamp = new Date().getTime
val end = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(endStamp)
println("开始时间:" + start + " ;结束时间:"+ end + " ;耗时约:" + (endStamp-startStamp)/1000 + "秒")

结果如下

+------+---+----------+----+------+
|  name|age|    skills|role|  team|
+------+---+----------+----+------+
|  科比| 40|   FADEWAY|  SG|LAKERS|
|  韦德| 33|LIGHTENING|null|  null|
|  麦迪| 41|      null|null|  null|
|  哈登| 29|          |  SG|  NETS|
|  罗斯| 30|     SPEED|  PG|KNICKS|
|  威少| 30|      DUNK|  PG|LAKERS|
|艾弗森| 41| CROSSOVER|null|  null|
|杜兰特| 30|     SCORE|null|  null|
|      | 30|          |null|  null|
|  老詹| 33|      KING|  SF|LAKERS|
+------+---+----------+----+------+
+--------+
|count(1)|
+--------+
|     920|
+--------+
开始时间:2022-01-17 10:32:51 ;结束时间:2022-01-17 10:32:59 ;耗时约:8

加缓存:耗时约3秒

//创建一个sparkSession对象
val conf = new SparkConf().setMaster("local[*]").setAppName("SparkHdfsOps")
    val sparkSession = SparkSession.builder()
      .config(conf)
      .getOrCreate()

//新建两个视图
//方式一:建视图之前缓存。如果只是需要对视图做操作的话,缓存dataframe效果不如直接缓存视图明显
println("创建临时表 math_df_table")
math_df.cache()
math_df.createOrReplaceTempView("math_df_table")
sparkSession.table("math_df_table").cache()//这里最好也缓存下
//方式二:建视图之后缓存
println("创建临时表 sports_df_table")
sports_df.createOrReplaceTempView("sports_df_table")
sparkSession.table("sports_df_table").cache()
//作join操作
println("join结果如下: ")
val startStamp = new Date().getTime
val start = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(startStamp)

sparkSession.sql("select a.name,a.age,a.skills,b.role,b.team from sports_df_table a left join math_df_table b on a.name=b.name").show(10)
sparkSession.sql("select count(*) from sports_df_table a left join math_df_table b " +
      "on a.name=b.name").show()
      
val endStamp = new Date().getTime
val end = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(endStamp)
println("开始时间:" + start + " ;结束时间:"+ end + " ;耗时约:" + (endStamp-startStamp)/1000 + "秒")
+------+---+----------+----+------+
|  name|age|    skills|role|  team|
+------+---+----------+----+------+
|  科比| 40|   FADEWAY|  SG|LAKERS|
|  韦德| 33|LIGHTENING|null|  null|
|  麦迪| 41|      null|null|  null|
|  哈登| 29|          |  SG|  NETS|
|  罗斯| 30|     SPEED|  PG|KNICKS|
|  威少| 30|      DUNK|  PG|LAKERS|
|艾弗森| 41| CROSSOVER|null|  null|
|杜兰特| 30|     SCORE|null|  null|
|      | 30|          |null|  null|
|  老詹| 33|      KING|  SF|LAKERS|
+------+---+----------+----+------+
+--------+
|count(1)|
+--------+
|     920|
+--------+
开始时间:2022-01-17 11:33:39 ; 结束时间:2022-01-17 11:33:43 ; 耗时约:3
  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZeroXu0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值