在Spark从2.1升级到2.3之后,我遇到了缓存的PySpark数据帧的问题。在Spark 2.1中,cache()方法对我来说是深层复制,即使它不像基于文档那样那样工作也是如此。
示例:
from pyspark import SparkContext, SparkConf
from pyspark.sql import SparkSession, HiveContext
from pyspark.sql import functions as spark_func
from pyspark.sql import Window
sparkSession = (SparkSession
.builder
.appName('process_name')
.enableHiveSupport()
.getOrCreate())
src_tbl = sparkSession.sql("SELECT * FROM src_tbl")
dst_tbl = sparkSession.sql("SELECT * FROM snpsht_tbl")
delta = src_tbl.subtract(dst_tbl) # find the difference
# find new records based on delta
new_records = delta.join(dst_tbl, how='left_anti', on=join_field).cache()
# create snpsht df
snpsht_tbl = dst_tbl.union(new_records)
# create incremental df
snpsht_tbl_tmp = snpsht_tbl.withColumn("row_nbr", spark_func.row_number(). \
over(Window.partitionBy(join_field). \
orderBy(spark_func.desc("last_modified_date"))))
inc_tbl = snpsht_tbl_tmp.filter("row_nbr = 1").drop("row_nbr")
inc_tbl.filter(spark_func.col("last_modified_date").isin(dt_today)).count() # 100 records
# save final tables to DB
snpsht_tbl_name = 'snpsht'
snpsht_tbl.write.mode("overwrite").saveAsTable(snpsht_table_name_tmp)
sparkSession.sql("""INSERT OVERWRITE TABLE snpsht_tbl +
SELECT * FROM snpsht_table_name_tmp""")
inc_tbl.filter(spark_func.col("last_modified_date").isin(dt_today)).count() # 0 records
inc_tbl_name = 'inc'
inc_tbl.write.mode("overwrite").saveAsTable(inc_table_name_tmp)
sparkSession.sql("""INSERT OVERWRITE TABLE inc_tbl +
SELECT * FROM inc_table_name_tmp""")
这是产生问题的最小示例。
现在,在Spark 2.1中,inc_tbl
已与所有新记录(从当日起)一起保存到inc_tbl
,其中包含使用缓存方法时存在的数据,并且是我想要的。在Spark 2.3中,有些东西可以从头算起所有转换,因此检查snpsht_tbl
表是否已经具有当前日期的记录,因此只需插入处理之前的记录即可。