You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

dbt快照生成重复dbt_scd_id,但源查询无重复的排查求助

问题分析与解决思路

针对你遇到的dbt快照生成重复dbt_scd_id、唯一键测试失败的问题,以下是核心原因排查和解决方法:


1. 自定义宏snapshot_latest_record逻辑存在漏洞

这是最常见的根源,即使你验证了最新导出数据无重复,也可能是宏的逻辑没有正确过滤出单次完整导出的数据集

  • 先直接执行宏生成的SQL,验证输出是否真的无重复ID:
    SELECT id, COUNT(*) AS row_count
    FROM ({{ snapshot_latest_record('your_source_table') }}) AS latest_data
    GROUP BY id
    HAVING row_count > 1
    
  • 如果查询返回结果,说明宏的逻辑错误:
    • 错误示例:如果宏是按ID分组取MAX(inserted_at_utc),可能会意外包含跨批次的重复ID(比如某个ID在旧批次未被新批次覆盖的极端情况);
    • 正确逻辑:应该直接取最新一次完整导出的所有行,即过滤inserted_at_utc等于最大导出时间的数据集:
      {% macro snapshot_latest_record(source_table) %}
          SELECT *
          FROM {{ source_table }}
          WHERE inserted_at_utc = (SELECT MAX(inserted_at_utc) FROM {{ source_table }})
      {% endmacro %}
      

2. dbt快照配置与宏的兼容性问题

即使宏输出正确,快照的check策略配置也可能引发重复:

  • 确认unique_key严格设置为id,且check_colshard_delete配置逻辑自洽:
    {% snapshot snap_boond__agencies %}
    {{
        config(
            target_schema='snapshots',
            strategy='check',
            unique_key='id',
            check_cols='all',
            hard_delete=true,
        )
    }}
    
    {{ snapshot_latest_record('source.boond.agencies') }}
    {% endsnapshot %}
    
  • 注意:如果check_cols设为all,dbt会对比包括inserted_at_utc在内的所有列,若每次导出的inserted_at_utc不同,即使其他列无变化,dbt也会生成新快照版本,但不会导致dbt_scd_id重复——除非同一次快照运行中同一个ID被多次处理。

3. dbt_scd_id生成逻辑的冲突

dbt_scd_id是dbt自动生成的主键,公式大致为:

MD5(CONCAT(COALESCE(CAST(id AS VARCHAR), 'null'), '|', COALESCE(CAST(dbt_valid_from AS VARCHAR), 'null')))

如果同一次快照运行中,同一个ID被宏返回多次,dbt_valid_from(快照运行时间)相同,就会生成完全一致的dbt_scd_id,触发主键重复错误。这直接说明宏的输出存在重复ID,必须优先修复宏逻辑。

4. 源表导出的隐性重复

即使你认为最新导出数据无重复,也可能存在隐性问题:

  • 直接查询源表最新批次数据,验证是否真的无重复:
    SELECT id, COUNT(*) AS row_count
    FROM your_source_table
    WHERE inserted_at_utc = (SELECT MAX(inserted_at_utc) FROM your_source_table)
    GROUP BY id
    HAVING row_count > 1
    
  • 如果有结果,说明导出工具存在重复插入的问题,需要修复源数据的导出逻辑。

5. 快照运行的并发冲突

如果快照运行时,源表的全量导出事务尚未提交,宏可能查询到不完整的中间数据,导致临时重复ID。解决方法:

  • 调整快照运行时机,确保在源表导出完成后再执行快照;
  • 在Snowflake中通过查询QUERY_HISTORY确认导出事务的提交状态。

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

火山引擎 最新活动