使用Delta Live Tables SCD Type 1加载数据遇更新检测错误求助
使用Delta Live Tables(DLT)实现SCD Type 1加载数据时,增量阶段触发以下错误:
"Detected a data update in the source table at version x. This is currently not supported. If you'd like to ignore updates, set the option 'ignoreChanges' to 'true'"
场景说明:
创建了charter和branch两个DLT表,branch表通过关联charter表获取charter_key。初始全量加载正常,但次日执行增量加载时触发上述错误。实际源数据未发生变更,但charter表对应的__apply_changes_storage_charter目录中,__UpsertVersion显示最新文件名、__Timestamp已更新,怀疑是该内部元数据变更被判定为源数据更新。
相关DLT代码
CREATE OR REFRESH STREAMING LIVE TABLE charter (charter_key bigint GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) ,charter_number int ,charter_name string ,charter_address1 string ,charter_address2 string ,charter_zip_code string) APPLY CHANGES INTO LIVE.charter FROM STREAM(LIVE.charter_bronze) KEYS (charter_number) SEQUENCE BY file_name COLUMNS * EXCEPT (file_name) CREATE OR REFRESH TEMPORARY STREAMING LIVE TABLE branch_stage AS SELECT c.charter_key ,b.branch_number ,b.branch_name ,b.branch_address1 ,b.branch_address2 ,b.branch_zip_code ,b.file_name FROM STREAM(LIVE.charter) c INNER JOIN STREAM(LIVE.branch_bronze) b ON c.charter_number = b.charter_number CREATE OR REFRESH STREAMING LIVE TABLE branch (branch_key bigint GENERATED ALWAYS AS IDENTITY (START WITH 1 INCREMENT BY 1) ,charter_key bigint ,branch_number int ,branch_name string ,branch_address1 string ,branch_address2 string ,branch_zip_code string) APPLY CHANGES INTO LIVE.branch FROM STREAM(LIVE.branch_stage) KEYS (charter_key, branch_number) SEQUENCE BY file_name COLUMNS * EXCEPT (file_name)
问题分析
- DLT的
APPLY CHANGES要求源为仅追加流,但STREAM(LIVE.charter)读取的是经过APPLY CHANGES生成的表——这类表内部会维护upsert状态(如__apply_changes_storage_*中的记录),即使源业务数据未变,内部元数据的更新也会被流读取判定为"数据更新",不符合APPLY CHANGES的源要求。 - SCD Type 1通过
APPLY CHANGES的KEYS匹配实现数据覆盖,核心是基于追加源的upsert操作,若源包含非追加的变更(哪怕是内部元数据变更),就会触发错误。
解决思路
调整branch_stage的数据源读取方式
由于charter是维度表,数据量通常不大,直接读取全量表而非流表,结合branch_bronze的流数据生成追加型的branch_stage:CREATE OR REFRESH TEMPORARY STREAMING LIVE TABLE branch_stage AS SELECT c.charter_key ,b.branch_number ,b.branch_name ,b.branch_address1 ,b.branch_address2 ,b.branch_zip_code ,b.file_name FROM LIVE.charter c -- 移除STREAM(),读取全量表 INNER JOIN STREAM(LIVE.branch_bronze) b ON c.charter_number = b.charter_number这样
branch_stage会成为纯追加流,满足APPLY CHANGES INTO branch的源要求。使用ignoreChanges参数忽略更新
若必须保留流读取charter的方式,可在APPLY CHANGES INTO branch中添加ignoreChanges = true选项,忽略源中的更新操作:APPLY CHANGES INTO LIVE.branch FROM STREAM(LIVE.branch_stage) KEYS (charter_key, branch_number) SEQUENCE BY file_name COLUMNS * EXCEPT (file_name) OPTIONS (ignoreChanges = true)注意:该选项会忽略所有源更新(包括真实业务数据更新),仅处理新追加记录,需确认场景无真实更新需求。
优化SEQUENCE BY字段
当前使用file_name作为SEQUENCE BY,若源文件每日重复生成(如全量覆盖生成同名文件),会被判定为新序列值触发重复upsert。建议改用源数据中的业务时间戳字段(若存在),或确保文件名包含唯一标识(如YYYYMMDD_版本号),避免无意义的序列更新。
内容的提问来源于stack exchange,提问作者AMN

