结构化流与批处理性能的差异

时间:2020-07-26 17:59:30

标签: apache-spark spark-structured-streaming azure-databricks

我们有一项工作可以在时间范围内汇总数据。我们是新兴的, 而且我们观察到运行时的性能特征明显不同 逻辑上与流与批处理作业相同的查询。我们想了解 发生了什么,并找到提高结构化速度的可能方法 基于流的方法。

就本文而言,假设架构为

root
 |-- objectId: long (nullable = true)
 |-- eventTime: long (nullable = true)
 |-- date: date (nullable = true)
 |-- hour: integer (nullable = true)

其中

  • datehour是(派生的)分区键,即实木复合地板文件存储在 像date=2020-07-26/hour=4这样的文件夹。
  • 底层格式类型为三角洲
  • 一个小时的数据约有2亿个事件
  • objectId广泛流传(一个小时内观察到1000万个不同的值, 分布非常不均匀)
  • 我们正在尝试计算5分钟时段内每个objectId的事件数
  • 基础资源从kafka队列流式传输(并每分钟运行一次)
    • 每分钟在ADL2上出现两个新文件,每个文件大小为25MB(实际文件 包含上面未显示的另外10列)

我们正在运行结构化的流媒体作业,主要是在做:

df.read.format("delta")
  .withWatermark("7 minutes") // watermark only applied to streaming query
  .groupBy($"date", $"hour", $"objectId", window($"eventTime", "5 minutes"))
  .coalesce(1) // debatable; we like limited number of files
  .partitionBy("date", "hour")
  .writeStream
  .format("delta")
  .option("checkpointLocation", <...>)
  .partitionBy("date", "hour")
  .start(<destination url>)
  .awaitTermination

关联的批处理作业基本上执行相同的操作,除了 withWatermark以及writeStream等的类似替代品。它的内容如下: 完全相同的源,因此它将读取完全相同的文件,具有相同的 大小等。

我们将这些运行在:

  • azure数据块
  • azure data lake gen 2

观察:

  • 批处理作业可以在大约一分钟的时间内运行一小时 在最小的群集(3个F4)上
  • 结构化的流作业OOM,即使使用(3x DS3_v2),也是如此 配置更大的实例(3个L4,每个节点32GB)
    • CPU实际上处于空闲状态(空闲率为97.4%)
    • 每个微型批次需要30到60s(几乎全部用在addBatch中)
    • 网络活动较少(可能为2MB /秒)
  • 通常,我觉得流媒体作业无法 当数据摄入量增加时(我们计划将流量提高10倍)会阻止

我的理解是,给定水印的流查询(7分钟) 窗口大小(5分钟)只需回看不到15分钟, 直到可以写出5分钟的窗口并丢弃所有关联状态为止。

问题:

  • 为什么基于结构化流的解决方案需要那么多的内存?
    • 假设我们必须保持大约1000万个条目的状态, 我不知道我们怎么需要那么多
  • 什么原因可能导致流作业的高处理时间 闲着吗?
  • 我应该看什么样的指标(在这里火花新手)?

1 个答案:

答案 0 :(得分:1)

df.read.format(“ delta”)

您似乎正在创建一个静态数据帧,然后将该静态数据帧转换为流式数据帧。聚合被应用于静态数据框,因此,窗口化可能不起作用。 尝试创建流数据帧:

  val DF = spark
  .readStream
  .format("delta")...

此处有一些示例https://docs.databricks.com/delta/delta-streaming.html#delta-table-as-a-stream-source

相关问题