Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pyspark 通过保存最新值将数据流传输到增量表_Pyspark_Spark Streaming_Databricks_Azure Databricks - Fatal编程技术网

Pyspark 通过保存最新值将数据流传输到增量表

Pyspark 通过保存最新值将数据流传输到增量表,pyspark,spark-streaming,databricks,azure-databricks,Pyspark,Spark Streaming,Databricks,Azure Databricks,我正在将一些温度数据从Azure事件中心流式传输到Databrick,并希望将最新的值存储在增量表中。对于每个传感器的温度值,我取过去五分钟的最大值。我似乎在用“向上插入”到增量表时碰到了一个块。每个设备的数据每10-15秒一次。我不确定是否正确使用writeStream,或者可能必须在数据帧上使用窗口函数来插入最新的聚合值 到目前为止,我已经在pysprak中创建了一个基本示例,看看它是否可以实现 #This sets up the data frame df = spark.read

我正在将一些温度数据从Azure事件中心流式传输到Databrick,并希望将最新的值存储在增量表中。对于每个传感器的温度值,我取过去五分钟的最大值。我似乎在用“向上插入”到增量表时碰到了一个块。每个设备的数据每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 *
  """)
因此,当第一次运行到一个空的增量表时,很好,五分钟后会出现合并冲突,因为它试图插入相同的值。它是不是试图升级整个数据帧而不是最新的项目


我已经看过滑动窗口在活动时间内进行分组,但这似乎不起作用。我正在考虑在micro-batch函数中添加一个窗口函数,这样它只会在有多个项的情况下插入最新的值,例如,一个在10:00am和10:05am的取整值,它将取10:05。建议?我想我的扳机没有扣对,也许吧?我试着把它上下缩小一分钟,但没有什么乐趣。

我想你忘了给你最近的SensorReads表加上t作为别名。你能试试吗

    MERGE INTO latestSensorReadings t
    USING updates s
    ON s.sensorId = t.sensorId
    WHEN MATCHED THEN UPDATE SET *
    WHEN NOT MATCHED THEN INSERT *

因此,在环顾四周,对流媒体做了更深入的研究之后,看起来我做得不对。为了让它执行我想要的操作,我需要在处理批处理之前删除分组

#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 *
  """)

很高兴知道你的问题已经解决了。48小时后,您可以将其作为答案接受(单击答案旁边的复选标记,将其从灰色变为填充)。这可能对其他社区成员有益。非常感谢。