Spark Dataframe在count()上返回不一致的值

时间:2018-08-06 09:47:28

标签: pyspark pyspark-sql

我正在使用pypark对从PostgreSQL数据库获得的数据执行一些计算。我的管道与此类似:

limit = 1000
query = "(SELECT * FROM table LIMIT {}) as filter_query"
df = spark.read.format("jdbc") \
        .option("url", "jdbc:postgresql://path/to/db") \
        .option("dbtable", query.format(limit)) \
        .option("user", "user") \
        .option("password", "password") \
        .option("driver", "org.postgresql.Driver")

df.createOrReplaceTempView("table")
df.count() # 1000

到目前为止,太好了。当我对数据执行一些转换时,问题开始了:

counted_data = spark.sql("SELECT column1, count(*) as count FROM table GROUP BY column1").orderBy("column1")
counted_data.count() # First value

counted_data_with_additional_column = counted_data.withColumn("column1", my_udf_function)
counted_data_with_additional_column.count() # Second value, inconsistent with the first count (should be the same)

第一个转换更改行数(值应为<= 1000)。但是,第二个不是,它只是添加了一个新列。对于count(),我怎么会得到不同的结果?

2 个答案:

答案 0 :(得分:1)

由于您使用的是Limit 1000,因此每次执行可能会获得不同的1000条记录。而且由于每次都会获得不同的记录,所以聚合的结果将有所不同。为了获得与Limit一致的行为,您可以尝试以下方法。

  1. 尝试使用cahce()或Persist方法来缓存数据帧,这将确保spark会使用相同的数据,直到其在内存中可用为止。

  2. 更好的方法可能是根据一些唯一的列对数据进行排序,然后获取1000条记录,这将确保您每次都获得相同的1000条记录。

希望有帮助。

答案 1 :(得分:0)

说明实际上很简单,但有点棘手。 Spark 可能对输入源(在本例中为数据库)执行附加读取。由于其他一些过程正在向数据库中插入数据,因此这些其他调用读取的数据与原始读取的数据略有不同,从而导致这种不一致的行为。读取后对df.cache()的简单调用将禁用进一步的读取。我通过分析数据库和计算机之间的通信量,以及确实发出了一些与我的转换匹配的其他SQL命令来弄清楚这一点。添加cache()通话后,没有其他流量出现。