我正在从Azure事件中心向Databricks发送一些温度数据,并希望将最新值存储在增量表中。对于每个传感器的温度值,我采用最近五分钟的最大值。我似乎对增量表的“更新”碰到了一个障碍。每台设备每10-15秒就会收到一次数据。我不确定我是在正确使用writeStream还是必须在数据帧上使用窗口函数来插入最新的加倍的值。
到目前为止,我已经在pysprak中创建了一个基本示例,以查看是否可以完成
#This sets up the data frame
df = spark.readStream.format("eventhubs").options(**ehConf).load().selectExpr("cast (body as string) as body")
# rounds up the time into 5 minutes
df = df.select(
get_json_object(df.body,'$.sensorId').alias('sensorId'),
get_json_object(df.body,'$.count').alias('temp'),
to_timestamp(from_unixtime(round(((get_json_object(df.body,'$.timestamp')/1000)/300))*300.0 ,"yyyy-MM-dd HH:mm:ss")).alias("roundedDatetime")
)
# Groups by the sensor id and round date
df = df.groupBy("sensorId", "roundedDatetime").agg(max("temp").cast("int").alias("temp"))
一切正常,我可以在5分钟的聚合级别看到数据
# Should insert trigger the batch every five minutes
query = (df.writeStream.format("delta").trigger(processingTime="5 minutes").foreachBatch(upsertToDelta).outputMode("update").start())
# this is my basic batch function, taken from the example docs on streaming
def upsertToDelta(microbatchdf, batchId):
microbatchdf.createOrReplaceTempView("updates")
microbatchdf._jdf.sparkSession().sql("""
MERGE INTO latestSensorReadings t
USING updates s
ON s.sensorId = t.sensorId
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *
""")
因此,当第一次运行到空的增量表时,它很好,五分钟后出现合并冲突,因为它试图插入相同的值。是否要尝试对整个数据框而不是最新数据进行重新插入?
我已经看过滑动窗口与事件时间进行分组的情况,但这似乎没有用。我正在考虑在微批处理功能中添加开窗功能,因此,如果有多个项目(例如,在10:00 am和10:05 am的舍入值中有一个以上),则它将仅插入该最新值,它将花费10:05一个。建议?我想我可能不太正确地触发触发器?我尝试将其上下移动一分钟,但没有任何乐趣。
答案 0 :(得分:0)
我认为您忘记为您的LatestSensorReadings表提供 t 作为别名。您可以尝试:
MERGE INTO latestSensorReadings t
USING updates s
ON s.sensorId = t.sensorId
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *
答案 1 :(得分:0)
因此,环顾四周并更深入地研究流媒体之后,似乎我做错了方向。为此,我需要在处理批处理之前删除分组。
#This sets up the data frame
df = spark.readStream.format("eventhubs").options(**ehConf).load().selectExpr("cast (body as string) as body")
# get the details from the event hub binary
df = df.select(
get_json_object(df.body,'$.sensorId').alias('sensorId'),
get_json_object(df.body,'$.count').alias('temp'))
因此,我只需要获取详细的详细信息,然后每5分钟处理一次该批处理。所以我的批处理功能如下:
# Should insert trigger the batch every five minutes
query = (df.writeStream.format("delta").trigger(processingTime="1 minutes").foreachBatch(upsertToDelta).outputMode("update").start())
# this is my updated batch function, now doing the grouping
def upsertToDelta(microbatchdf, batchId):
microbatchdf = microbatchdf.groupBy("sensorId").agg(max("temp").cast("int").alias("temp"))
microbatchdf = microbatchdf.withColumn("latestDatetime", current_timestamp())
microbatchdf.createOrReplaceTempView("updates")
microbatchdf._jdf.sparkSession().sql("""
MERGE INTO latestSensorReadings t
USING updates s
ON s.sensorId = t.sensorId
WHEN MATCHED THEN UPDATE SET *
WHEN NOT MATCHED THEN INSERT *
""")