如何使用具有Spark数据流结构的非基于时间的窗口?

时间:2019-04-09 11:26:53

标签: pyspark apache-spark-sql spark-streaming

我试图在带有Spark和Kafka的结构化流上使用窗口。 我在非基于时间的数据上使用窗口,所以出现此错误:

'Non-time-based windows are not supported on streaming DataFrames/Datasets;;\nWindow

这是我的代码:

window = Window.partitionBy("input_id").orderBy("similarity")
outputDf = inputDf\
        .crossJoin(ticketDf.withColumnRenamed("IDF", "old_IDF")) \
        .withColumn("similarity", cosine_similarity_udf(col("IDF"), col("old_IDF"))) \
        .withColumn("rank", rank().over(window)) \
        .filter(col("rank") < 10)

所以我正在寻找技巧或参考,以在基于非时间的数据上使用窗口...

3 个答案:

答案 0 :(得分:1)

Spark结构化流不支持使用over()的传统SQL窗口(它唯一支持的窗口是基于时间的窗口)。如果您考虑一下,可能是为了避免混淆。有些人可能会错误地认为Spark结构化流可以基于列对整个数据进行分区(这是不可能的,因为流是无限制的输入数据)。

您可以使用groupBy()groupBy()也是一个全状态操作,除非在我们要进行groupBy操作的列列表中包括一个timestamp列,否则无法在append模式下实现。例如:

df_result = df.withWatermark("createdAt", "10 minutes" ) \
              .groupBy( F.col('Id'), window(F.col("createdAt"), self.acceptable_time_difference)) \
              .agg(F.max(F.col('createdAt')).alias('maxCreatedAt'))

在此示例中,createdAt是时间戳类型的列。请注意,在这种情况下,我们必须事先在timestamp列上调用withWatermrke,因为Spark无法无限存储状态。

ps:我知道groupBy不能完全像窗口一样工作,但是只要使用mapGroupsWithState进行简单的联接或自定义功能,就可以实现所需的功能。

答案 1 :(得分:0)

Windows始终需要基于时间的数据,但Spark Structured Streaming不需要。

您可以使用触发器“ as_soon_as_posible” 创建Spark Structured Streaming,并且可以按窗口对数据进行分组,分组是按时进行的。

参考:https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html#window-operations-on-event-time

答案 2 :(得分:0)

实际上,窗口仅基于时间...

对于应用程序,我避免避免使用烧瓶。我已经寻找流媒体系统很长时间了...现在我正在使用Kafka,它在我的应用程序中摇摇欲坠! :)

我想与您分享有关结构化流式传输不支持的操作的信息:https://spark.apache.org/docs/latest/structured-streaming-programming-guide.html#unsupported-operations