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

Pyspark Spark Dataframe在count()上返回不一致的值,pyspark,pyspark-sql,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(li

我正在使用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)

第一个转换改变了行数,(值应该是解释其实很简单,但有点棘手。Spark可能会对输入源执行额外的读取(在本例中是数据库)。由于其他进程正在数据库中插入数据,因此这些附加调用读取的数据与原始读取的数据略有不同,从而导致这种不一致的行为。只需调用
df.cache()
读取后禁用进一步读取。我通过分析数据库和我的计算机之间的通信量,以及一些与我的转换相匹配的SQL命令来解决这个问题。添加
缓存()后
调用,没有出现进一步的流量。

解释其实很简单,但有点棘手。Spark可能会对输入源(在本例中为数据库)执行额外的读取。由于其他进程正在数据库中插入数据,因此这些附加调用读取的数据与原始读取的数据略有不同,从而导致这种不一致的行为。只需调用
df.cache()
读取后禁用进一步读取。我通过分析数据库和我的计算机之间的通信量,以及一些与我的转换相匹配的SQL命令来解决这个问题。添加
缓存()后
调用时,没有出现进一步的流量。

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

  • 尝试使用cahce()或Persist方法缓存数据帧,这将确保spark在内存中可用之前使用相同的数据

  • 但更好的方法可能是根据某个唯一的列对数据进行排序,然后获得1000条记录,这将确保每次获得相同的1000条记录


  • 希望有帮助。

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

  • 尝试使用cahce()或Persist方法缓存数据帧,这将确保spark在内存中可用之前使用相同的数据

  • 但更好的方法可能是根据某个唯一的列对数据进行排序,然后获得1000条记录,这将确保每次获得相同的1000条记录


  • 希望能有所帮助。

    谢谢!我实际上写了这个问题来记录这种行为,这不仅发生在运行整个计算之后,而且也发生在中间步骤。我使用了
    缓存
    选项,因为查询只是可能发生这种情况的一个示例。谢谢!我确实写了这个问题记录这种行为,这不仅发生在运行整个计算之后,而且也发生在中间步骤上。我使用了
    cache
    选项,因为查询只是可能发生这种情况的一个示例。请记住,您不应该依赖于cache来确定正确性。缓存可以在任何时候被逐出,而无需任何修改您甚至意识到了这一点。@user8371915这一点很好。在进一步计算之前,我可能会将读取的数据保存到磁盘上,或者确保查询始终返回相同的数据。请记住,您不应该依赖缓存来确定正确性。缓存可以在您不知道的情况下随时被逐出。@user8371915这一点很好。@user8371915t、 我可能会在进一步计算之前将读取的数据保存到磁盘,或者确保查询始终返回相同的数据。