我想在Spark Structured Streaming中进行多次聚合。
这样的事情:
当我在Structured Streaming中运行它时,它会给我一个错误"流数据框架/数据集"不支持多个流聚合。
有没有办法在结构化流媒体中进行这样的多重聚合?
答案 0 :(得分:9)
这不受支持,但还有其他方法。就像执行单个聚合并将其保存到kafka一样。从kafka读取并再次应用聚合。这对我有用。
答案 1 :(得分:1)
您未提供任何代码,因此我将使用引用here的示例代码。
让我们假设下面是DF使用的初始代码。
import pyspark.sql.functions as F
spark = SparkSession. ...
# Read text from socket
socketDF = spark \
.readStream \
.format("socket") \
.option("host", "localhost") \
.option("port", 9999) \
.load()
socketDF.isStreaming() # Returns True for DataFrames that have streaming sources
socketDF.printSchema()
# Read all the csv files written atomically in a directory
userSchema = StructType().add("name", "string").add("age", "integer")
csvDF = spark \
.readStream \
.option("sep", ";") \
.schema(userSchema) \
.csv("/path/to/directory") # Equivalent to format("csv").load("/path/to/directory")
按名称分组df并应用汇总功能 count , sum 和 balance 。
grouped = csvDF.groupBy("name").agg(F.count("name"), F.sum("age"), F.avg("age"))
答案 2 :(得分:0)
Spark 2.0不支持此功能,因为Structured Streaming API仍处于试验阶段。请参阅here以查看所有当前限制的列表。
答案 3 :(得分:0)
对于spark 2.2及更高版本(不确定早期版本),如果您可以将聚合设计为在 append 模式下使用 flatMapGroupWithState ,则可以进行与你要。 这里提到了限制Spark structured streaming - Output mode
答案 4 :(得分:0)
从Spark 2.4开始,不支持Spark结构化流中的多个聚合。支持这一点尤其棘手。事件时间处于“更新”模式,因为合计输出可能会随事件的发生而改变。在“追加”模式下支持此功能非常简单,但是spark目前还不支持真正的水印。
这里有一个提案以“附加”模式添加-https://github.com/apache/spark/pull/23576
如果有兴趣,您可以观看PR,并在此处张贴投票。
答案 5 :(得分:0)
从Spark结构化流2.4.5开始,无状态处理中不支持多种聚合。 但是,如果需要状态处理,则可以多次聚合。
在附加模式下,您可以对分组数据集(通过使用flatMapGroupWithState
API获得)上的groupByKey
API多次使用。
答案 6 :(得分:0)
TLDR-不支持此功能;在某些情况下,可能有解决方法。
长版-
在某些情况下,可以使用解决方法,例如,如果您希望在低基数列的流查询中包含多个count(distinct)
,那么approx_count_distinct
实际返回<通过将rsd
自变量放到足够低的位置,可以精确计算出不同元素的数量(这是rox_count_distinct的第二个可选参数,默认为0.05
。)
这里如何定义“低基数”?对于具有超过1000个唯一值的列,建议不要使用这种方法。
因此,在流式查询中,您可以执行以下操作-
(spark.readStream....
.groupBy("site_id")
.agg(approx_count_distinct("domain", 0.001).alias("distinct_domains")
, approx_count_distinct("country", 0.001).alias("distinct_countries")
, approx_count_distinct("language", 0.001).alias("distinct_languages")
)
)
这里证明它确实有效:
请注意,count(distinct)和count_approx_distinct
给出相同的结果!
这是有关rsd
参数count_approx_distinct
的一些指导:
rsd
为 0.02 的列,是必需的; rsd
为 0.001 的列,是必需的。 PS。另请注意,由于我没有足够的耐心来完成该实验,因此不得不在具有10k个不同值的列上注释掉该实验。这就是为什么我提到您不应该对具有超过1k个不同值的列使用此技巧。为了使approx_count_distinct
匹配超过1k个不同值的精确计数(差异),对于HyperLogLogPlusPlus algorithm的设计目标而言,rsd
的方式可能太低了(该算法落后于roximate_count_distinct实现)。
正如其他人所提到的,您可以使用Spark的arbitrary stateful streaming来实现自己的聚合;并使用[flat]MapWithGroupState在单个流上根据需要进行尽可能多的聚合。与上述仅在某些情况下有效的黑客不同,这是一种合法且受支持的方法。此方法仅适用于Spark Scala API,不适用于PySpark。
一种正确的方法是在Spark Streaming中显示对本机多重聚合的支持-https://github.com/apache/spark/pull/23576-对此SPARK jira / PR投赞成票,如果对此感兴趣,请显示您的支持。