又是一个采坑之旅。
scala的算子分为两类,transformer算子和action算子。
由于scala是惰性的,在transformer算子执行时,只是记录这个操作,而并没有真正的执行,只有遇到action算子,才会将之前的所有操作真正执行。
因此,当在transformer之后,多次进行action调用,若没有持久化,是重复运行的,也就是说,假如你在dataframe里生成了一列随机数,后面先用这个随机数做了列变换,然后再用对这个dataframe做筛选之类的操作。比如这样:
val random = udf { (count:Long) => {
scala.util.Random.nextDouble()
}
}
val sample = 0.0001
df_sdk_filter0 =df_sdk_filter0.withColumn("rand",random( col("count")))
val cal_p = udf { (count:Long, rand:Double) => {
val p = 1-(sample*all_count/count+math. sqrt(sample*all_count/count))
var res=1
if (p>rand){
res=0
}
else{
res=1
}
res
}
}
//先生成一列flag,判断随机数与计算出的公式大小
df_sdk_filter0 = df_sdk_filter0.withColumn("flag", cal_p($"count", $"rand"))//.persist()
df_sdk_filter0.show()
//再对flag进行筛选
val df_sdk_filter = df_sdk_filter0.filter("flag=1")
这两个action操作,得到的结果是不一样的,因为相当于随机数运行了两次
所以先persist持久化,才能保证之后的所有对随机数进行的操作,都是针对同一个随机数,而不会变化。