2

在使用 Databricks Spark 执行 ACID 操作时,我们遇到了一个棘手的情况。我们希望使用 PySpark 通过 JDBC 连接对 Azure Synapse 表执行 UPSERT。我们知道 Spark 只提供了 2 种数据写入模式。APPENDOVERWRITE(在我们的例子中只有这两个使用 full)。因此,基于这两种模式,我们想到了以下选项:

  1. 我们将把整个数据框写入一个阶段表。我们将使用这个阶段表对最终表执行 MERGE 操作(~UPSERT)。阶段表将在此之后被截断/删除。

  2. 我们还将把目标表数据带入 Spark。在 Spark 内部,我们将使用 Delta Lake 执行 MERGE,并将生成最终的 Dataframe 。此数据帧将以 OVERWRITE 模式写回 Target 表。

考虑到缺点。双方..

在选项 1 中,我们必须使用两个表来写入最终数据。如果 Stage 和 target 表都很大,那么在 Synapse 中执行 MERGE 操作是另一项艰巨的任务,可能需要时间。

在选项 2 中,我们必须将 Target 表放入内存中的 Spark。尽管网络 IO 不是我们关心的问题,因为 Databricks 和 Synpse 都在同一个 Azure AZ 中,但它可能会导致 Spark 端的内存问题。

还有其他可行的选择吗??或者有什么推荐吗??

4

2 回答 2

1

答案将取决于您的问题中未列出的许多因素。这是一个非常开放的问题。

(鉴于您的问题的表述方式,我假设您使用的是专用 SQL 池而不是按需突触)

以下是一些想法:

  • 您将在选项 1 中使用 spark 集群的计算,在选项 2 中使用 Synapse 的计算。比较成本。
    • 选择成本较低的。
  • 使用他们的驱动程序从 Spark 向/从 Synapse 读取和写入数据,使用 Datalake 作为阶段。即,在将 Synapse 中的表读取到 Spark 中的 datafrmae 时,驱动程序将首先使 Synapse 将数据导出到 Datalake(作为 parquet IIRC),然后读取 Datalake 中的文件以创建 Dataframe。如果您谈论的是 10 或数百万或数十亿行,这可以很好地扩展。但是,如果行数很少(10-100 千),开销可能会成为性能开销。
    • 测试并选择更快的。
  • 请记住,Synapse 不像传统的 MySQL 或 SQL-Server。这是一个 MPP 数据库。
    • "performing MERGE operation inside Synapse is another herculean task and May take time"是错误的说法。它可以像 Spark 集群一样扩展。
    • It may leads to memory issue in Spark side, 是和不是。一方面,所有数据都不会加载到单个工作节点中。OTOH 是的,每个节点都需要足够的内存来完成它自己的部分。
  • 虽然 Synapse 可以动态放大和缩小,但我发现完成放大需要 40 分钟。另一方面,Databricks 是完全按需的,您可以通过打开集群、执行 upsert、关闭集群来摆脱困境。使用 Synapse,您可能会有其他客户端使用它,因此可能无法将其关闭。
    • 因此,使用 Synapse 时,您必须为每个 upsert(放大、upsert、缩小)忍受 40-80 分钟的停机时间,或者
    • 一直支付高 DWU 统一费率,尽管只有当您更新插入时您的使用率很高,但其他情况下它非常低。
  • 最后,请记住,MERGE在撰写本文时它处于预览状态。如果您的产品因使用 MERGE 而中断,则意味着没有 Sev-A 支持案例/立即支持。
    • 您始终可以使用DELETE+INSERT代替。假设您收到的增量包含目标表中的所有列,而不仅仅是更新的列。
于 2021-06-01T22:53:10.850 回答
0

您是否尝试创建校验和以仅对具有实际数据更改的行进行合并更新?

于 2020-09-10T00:17:44.847 回答