ETL增量加载中使用>和<=时的安全取值逻辑咨询
ETL增量加载数据不遗漏的方案选择
你的核心问题是原逻辑存在数据永久遗漏风险:当你获取@current_max_date(记为T)之后、增量查询结束之前,源表插入了时间戳等于T的记录,这条记录既不会被本次ETL的TIMESTAMP_Column <= T捕获(查询执行于插入操作之前),也不会被下次ETL的TIMESTAMP_Column > T捕获(它的时间等于下次的@last_run),最终导致这条记录永远无法被加载。
下面分析你提出的两个方案:
方案1:对@current_max_date减去1秒
这个方案不可靠,存在明显缺陷:
- 无法适配高精度时间戳:如果源表时间戳包含毫秒/微秒级精度,减1秒会直接排除
T-1秒到T之间的所有记录,比如原T是2024-05-20 10:00:00.000,减1秒后是2024-05-20 09:59:59.000,那么时间戳为2024-05-20 09:59:59.123到2024-05-20 10:00:00.000的记录都会被排除,若下次ETL的@current_max_date未更新到更大值,这些记录会持续遗漏。 - 本质是通过缩小加载范围规避问题,反而引入了新的遗漏风险,属于治标不治本。
方案2:修改查询条件为TIMESTAMP_Column >= @last_run and TIMESTAMP_Column < @current_max_date
这个方案能彻底解决数据遗漏问题,逻辑闭环清晰:
- 本次ETL加载**从
@last_run(包含)到@current_max_date(不包含)**的所有记录,确保当前已存在的符合范围的记录全部被捕获。 - 若在获取
@current_max_date之后插入了时间戳等于@current_max_date的记录,下次ETL时@last_run会被设置为本次的@current_max_date,此时查询条件TIMESTAMP_Column >= @last_run会包含这条记录,保证它被正常加载。 - 该逻辑也兼容初始全量加载:第一次运行时将
@last_run设为极小值(比如'1900-01-01'),TIMESTAMP_Column >= 极小值 and < 当前最大时间会加载所有现有记录,满足全量需求。
调整后的完整SQL逻辑
-- 加载增量/全量数据 INSERT INTO SINK_TBL SELECT * FROM Data_Source_Table WHERE TIMESTAMP_Column >= @last_run AND TIMESTAMP_Column < @current_max_date; -- 更新水印表 INSERT INTO watermark(tablename, dt) VALUES ('table_name', @current_max_date);
内容的提问来源于stack exchange,提问作者variable
相关产品推荐
相关产品推荐

