You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delta Live Tables(DLT)中硬删除的处理方案咨询

在Delta Live Tables中处理硬删除的实践方案分析

针对你提到的场景——无法获取源系统变更日志,依赖每日全量主键列表,基于Autoloader+DLT apply_changes构建SCD-1/SCD-2的silver表——下面逐一分析你列出的三个方案,并给出实操建议:

方案1:调用apply_changes后,利用主键列表识别已删除数据

核心逻辑

先通过apply_changes完成bronze到silver的增量新增/更新同步,再将silver表中当前活跃的主键(SCD-2中对应end_date IS NULL的记录,SCD-1直接取所有主键)与每日全量主键列表做对比,找出不在列表中的主键即为已删除数据,最后对silver表执行删除标记或物理删除操作。

优缺点

  • 优势:逻辑拆分清晰,不干扰原有apply_changes的同步流程,对SCD-1和SCD-2的适配性都很强。
  • 劣势:需要额外的处理步骤,两次操作存在短暂的数据窗口不一致;如果是物理删除,需确保符合数据留存合规要求。

实操示例(SCD-2场景)

在DLT管道中新增一个处理删除的步骤:

from delta.tables import DeltaTable
from pyspark.sql.functions import current_timestamp, lit, col

@dlt.table(name="silver_scd2_final")
def process_scd2_deletes():
    # 读取apply_changes生成的基础SCD2表
    silver_scd2_base = dlt.read("silver_scd2_base")
    # 读取每日全量主键列表
    daily_full_pks = spark.read.table("daily_full_primary_keys")
    
    # 找出当前活跃且不在全量列表中的主键(即已删除)
    deleted_pks = silver_scd2_base.filter(col("end_date").isNull()) \
        .select("id") \
        .join(daily_full_pks, on="id", how="left_anti")
    
    # 转换为DeltaTable执行合并更新
    silver_scd2_delta = DeltaTable.forPath(spark, dlt.read("silver_scd2_base").inputFiles()[0])
    silver_scd2_delta.alias("target").merge(
        deleted_pks.alias("source"),
        "target.id = source.id AND target.end_date IS NULL"
    ).whenMatchedUpdate(
        set={"end_date": current_timestamp(), "is_deleted": lit(True)}
    ).execute()
    
    # 返回更新后的表
    return spark.read.table("silver_scd2_base")

方案2:在bronze层标记已删除记录

核心逻辑

在bronze表加载完成后,将bronze表的主键与每日全量主键列表对比,给不在列表中的记录添加is_deleted = True的标记,后续apply_changes时直接将这个标记带入silver层,统一处理新增/更新/删除。

优缺点

  • 优势:删除逻辑前置,silver层无需额外步骤,apply_changes可以一次性处理所有变更类型。
  • 劣势:破坏了bronze表作为源数据镜像的特性;如果源系统存在数据同步延迟,可能误将未同步的新增数据标记为删除。

注意事项

必须确保每日全量主键列表是源系统当日最终状态的集合,建议增加缓冲校验逻辑(比如对比连续两日的全量列表,仅标记连续两日都不在列表中的记录为删除),避免误操作。

方案3:DLT管道完成后,通过二次事务处理删除

核心逻辑

DLT管道正常执行完apply_changes流程后,单独启动一个独立事务,用每日全量主键列表对比silver表,处理删除操作。

优缺点

  • 优势:完全不侵入原有DLT管道逻辑,作为补全步骤存在。
  • 劣势:需要额外调度这个事务,增加运维复杂度;两次事务之间存在时间差,数据一致性窗口更长;若DLT管道失败,该步骤可能无法触发,导致删除遗漏。

推荐实践

  • 对于SCD-1场景:优先选择方案1,在DLT内部完成删除处理,逻辑闭环且运维成本低。可以直接通过join标记删除状态,或执行物理删除(需合规)。
  • 对于SCD-2场景:方案1是最优选择,因为需要为已删除记录生成新的版本(更新end_date),符合SCD-2的版本化特性。
  • 无论哪种方案,都要注意:
    1. 验证每日全量主键列表的准确性,避免因源系统导出问题导致的误删。
    2. 针对数据延迟场景,增加缓冲机制(比如延迟1天处理删除,或校验记录的最后更新时间)。
    3. 对大表做分区或索引优化,提升主键对比的性能。

内容的提问来源于stack exchange,提问作者FoxHound

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 03:33:15