我正在尝试将Puds udf应用于pyspark结构化流的窗口。问题在于,流一旦赶上当前状态,所有新窗口就会以某种方式仅包含一个值。
正如您在屏幕快照中看到的那样,2019-10-22T15:34:08.730 + 0000之后的所有窗口都只包含一个值。用于生成此代码的代码是这样的:
@pandas_udf("Count long, Resampled long, Start timestamp, End timestamp", PandasUDFType.GROUPED_MAP)
def myudf(df):
df = df.dropna()
df = df.set_index("Timestamp")
df.sort_index(inplace=True)
# resample the dataframe
resampled = pd.DataFrame()
oidx = df.index
nidx = pd.date_range(oidx.min(), oidx.max(), freq="30S")
resampled["Value"] = df.Value.reindex(oidx.union(nidx)).interpolate('index').reindex(nidx)
return pd.DataFrame([[len(df.index), len(resampled.index), df.index.min(), df.index.max()]], columns=["Count", "Resampled", "Start", "End"])
predictionStream = sensorStream.withWatermark("Timestamp", "90 minutes").groupBy(col("Name"), window(col("Timestamp"), "70 minutes", "5 minutes"))
predictionStream.apply(myudf).writeStream \
.queryName("aggregates") \
.format("memory") \
.start()
流确实每5分钟获取新值。只是该窗口以某种方式仅从最后一批中获取值,即使水印不应该过期也是如此。
我在做错什么吗?我已经尝试过玩水印了。对结果没有影响。我需要udf内部窗口的所有值。
我在设置为5.5 LTS ML(包括Apache Spark 2.4.3,Scala 2.11)的群集上的数据砖中运行此程序
答案 0 :(得分:0)
您似乎可以为writeStream指定所需的输出模式
See documentation at Output Modes
默认情况下,它使用附加模式:
这是默认模式,在该模式下,仅将自上次触发以来添加到结果表中的新行输出到接收器。
尝试使用:
predictionStream.apply(myudf).writeStream \
.queryName("aggregates") \
.format("memory") \
.outputMode(OutputMode.Complete) \
.start()
答案 1 :(得分:0)
我发现了一个关于此问题的 Spark JIRA issue,但它没有解决就关闭了。该错误似乎是,我在 Spark 3.1.1 版上独立确认了这一点,即 Pandas UDF 在每个触发器上仅使用自上次触发器以来的数据执行。因此,您可能只处理要在每个触发器中考虑的数据子集。 Grouped Map Pandas UDF 似乎不适用于具有增量表源的结构化流。如果您之前找到了解决方案,请继续跟进,否则我会把这个留在这里给也找到这个线程的人。
编辑:Databricks 论坛中有一些讨论,关于首先进行流式聚合,然后使用 Pandas UDF(可能需要一个包含数组的列的单个记录),如下所示。我尝试过这个。有用。但是,我的批处理持续时间很长,我不确定这些额外的工作对它的贡献有多大。
agg_exprs = [f.collect_list('col_of_interest_1'),
f.collect_list('col_of_interest_2'),
f.collect_list('col_of_interest_3')]
intermediate_sdf = source_sdf.groupBy('time_window', ...).agg(agg_exprs)
final_sdf = intermediate_sdf.groupBy('time_window', ...).applyInPandas(func, schema)