在 Azure Databricks 上使用联接

Databricks 支持 ANSI 标准联接语法。 本文介绍使用批处理或流式处理的联接之间的差异,并提供优化联接性能的一些建议。

注意

Databricks 还支持集运算符 UNIONINTERSECTEXCEPT 的标准语法。 请参阅集运算符

流式处理和批处理联接之间的差异

Azure Databricks 上的联接是有状态的或无状态的。

所有批处理联接都是无状态联接。 结果会立即处理,并在查询运行时反映数据。 每次执行查询时,都会根据指定的源数据计算新结果。 请参阅批处理联接

两个流式处理数据源之间的联接是有状态的。 在有状态联接中,Azure Databricks 会跟踪有关数据源和结果的信息,并迭代更新结果。 有状态联接可以为联机数据处理提供强大的解决方案,但很难有效地实施。 它们具有复杂的操作语义,具体取决于输出模式、触发器间隔和水印。 请参阅流之间的联接

流静态联接是无状态的,但它为增量数据源(如事实数据表)与静态数据源(如渐变维度表)的联接提供了一个不错的选择。 每次执行查询时,不联接来自双方的所有记录,而是仅将来自流源的新接收的记录与静态表的当前版本联接。 请参阅流静态联接

批处理联接

Azure Databricks 支持标准 SQL 联接语法,包括内、外、半、反、交叉联接。 请参阅联接

流之间的联接

联接两个流式处理数据源可能会对管理状态信息以及对结果计算和输出的推理带来重大挑战。 在实现流之间的联接之前,Databricks 建议深入了解有状态流式处理的操作语义,包括水印如何影响状态管理。 请参阅以下文章:

Databricks 建议为所有流之间的联接的两侧指定水印。 支持以下联接类型:

  • 内联
  • 左外部联接
  • 右外部联接
  • 完全外部联接
  • 左半联接

请参阅有关流之间的联接的 Apache Spark 结构化流式处理文档。

流静态联接

注意

对流静态联接描述的行为假定静态数据是使用 Delta Lake 存储的。

流静态联接使用无状态联接将最新有效版本的 Delta 表(静态数据)联接到数据流。

当 Azure Databricks 处理流静态联接中的微批处理数据时,静态 Delta 表中的最新有效数据版本将与当前微批处理中存在的记录联接。 由于联接是无状态的,因此无需配置水印,并且可以以低延迟处理结果。 联接中使用的静态 Delta 表中的数据应缓慢变化。

下面的示例对此模式进行了演示:

streamingDF = spark.readStream.table("orders")
staticDF = spark.read.table("customers")

query = (streamingDF
  .join(staticDF, streamingDF.customer_id==staticDF.id, "inner")
  .writeStream
  .option("checkpointLocation", checkpoint_path)
  .table("orders_with_customer_info")
)

优化联接性能

启用了 Photon 的计算始终选择最佳联接类型。 请参阅什么是 Photon?

使用启用了 Photon 的近期 Databricks Runtime 版本时,通常可提供良好的联接性能,但还应考虑以下建议:

  • 交叉联接非常昂贵。 从需要低延迟或频繁重新计算的工作负载和查询中移除交叉联接。
  • 联接的顺序很重要。 执行多个联接时,请始终先联接最小的表,然后将结果与较大的表联接。
  • 优化器在处理具有许多联接和聚合的查询时会很吃力。 保存中间结果可以加速查询规划和计算结果。
  • 保持更新的统计信息以提高性能。 可运行查询 ANALYZE TABLE table_name COMPUTE STATISTICS 来更新查询规划器中的统计信息。

注意

在 Databricks Runtime 14.3 LTS 及更高版本中,可以修改 Delta Lake 为跳过数据收集统计信息的列,然后在 Delta 日志中重新计算现有统计信息。 请参阅指定增量统计信息列

Azure Databricks 上的联接提示

Apache Spark 支持指定范围联接和倾斜联接的联接提示。 不需要倾斜联接的提示,因为 Azure Databricks 会自动优化这些联接。 请参阅提示

如果联接性能不佳并且你在执行非等值联接,则范围联接的提示可能会有用。 例子包括联接时间戳范围或聚类分析 ID 的范围。 请参阅范围联接优化