2026/5/21 11:01:51
网站建设
项目流程
几百块做网站,平面设计培训班教程,wordpress设置标题字体,百度广告一天多少钱1. Deduplication 是什么#xff0c;为什么流式场景尤其需要
Deduplication#xff08;去重#xff09;是在一组列#xff08;去重键#xff09;上移除重复行#xff0c;只保留第一条或最后一条记录。典型原因是#xff1a;上游 ETL 不是端到端 exactly-once#xff0…1. Deduplication 是什么为什么流式场景尤其需要Deduplication去重是在一组列去重键上移除重复行只保留第一条或最后一条记录。典型原因是上游 ETL 不是端到端 exactly-once故障恢复/重试可能把同一业务事件写了多次导致下游 SUM/COUNT 等统计被“重复行”污染所以需要在进一步分析前先做去重。(Apache Nightlies)从实现角度看Flink SQL 的去重本质上就是 Top-N 的特例N 1并且按处理时间或事件时间排序。(Apache Nightlies)2. Flink SQL 去重的标准写法优化器识别模式2.1 QUALIFY 写法更简洁官方给出的 Deduplication 语法是对去重键PARTITION BY按时间属性ORDER BY保留ROW_NUMBER() 1。(Apache Nightlies)SELECT[column_list]FROMtable_name QUALIFY ROW_NUMBER()OVER(PARTITIONBYcol1[,col2...]ORDERBYtime_attr[ASC|DESC])1;2.2 子查询 WHERE rownum 1更通用适配更多版本很多生产环境更习惯用这版逻辑更直观并且必须包含rownum 1否则优化器可能无法把它翻译成 Deduplicate 算子。(Apache Nightlies)SELECT[column_list]FROM(SELECT*,ROW_NUMBER()OVER(PARTITIONBYcol1[,col2...]ORDERBYtime_attr[ASC|DESC])ASrownumFROMtable_name)WHERErownum1;3. 参数语义去重键、保留第一条/最后一条、必须是“时间属性”3.1 PARTITION BY去重键deduplicate keyPARTITION BY col1[, col2...]就是你判定“重复”的那组字段比如 order_id、message_id、(user_id, item_id) 等。(Apache Nightlies)3.2 ORDER BY time_attr决定保留第一条还是最后一条排序列必须是时间属性processing time 或 event time。(Apache Nightlies)ORDER BY time_attr ASC保留最早的一条first rowORDER BY time_attr DESC保留最新的一条last row(Apache Nightlies)3.3 处理时间 vs 事件时间结果是否“可复现”经验上强烈建议优先用事件时间rowtime做去重排序一些调优/最佳实践文档也明确指出按 processing time 去重结果会随运行时机波动按 event time 去重结果更确定、更可复现。(Ververica 文檔)4. 示例按 order_id 去重只保留第一次出现你给的 Orders 例子CREATETABLEOrders(order_id STRING,userSTRING,product STRING,numBIGINT,proctimeASPROCTIME())WITH(...);-- 按 order_id 去重保留第一次出现ASCSELECTorder_id,user,product,numFROM(SELECT*,ROW_NUMBER()OVER(PARTITIONBYorder_idORDERBYproctimeASC)ASrow_numFROMOrders)WHERErow_num1;这个模式正是 Flink 官方去重示例中强调的写法ROW_NUMBER 分区键 时间排序 rownum 1。(Apache Nightlies)5. 去重的 Changelog 语义为什么下游可能会看到 UPDATE/撤回流式去重不是“简单过滤一次”——当更早/更晚的记录到来时尤其事件时间乱序去重结果可能需要被修正因此会产生changelog更新流。在 Flink SQL 的 retract 机制里更新通常会被拆成DELETE(-U)INSERT(U)两条事件先撤回旧值再发新值。(Confluent)工程结论你的 sink/下游必须能消费更新流upsert/retract否则结果会错或写不进去。6. Sink 选型建议优先 Upsert 型尤其写 Kafka / 外部库如果你把去重结果写入 Kafka官方upsert-kafka明确支持消费 changelog会把 INSERT/UPDATE_AFTER 写成正常消息把 DELETE 写成 tombstone。(Apache Nightlies)落外部存储JDBC、KV、OLAP时同样建议使用Upsert 语义主键一致让“同一 key 的最新结果”被覆盖更新。7. 状态与 TTL去重会“记住 key”不设 TTL 可能越跑越大去重需要维护“某个 key 当前保留的是哪一条”因此会占用 state。Flink Table/SQL 提供table.exec.state.ttlIdle State Retention Time用来控制 key 的状态多久没更新就清理。(Apache Nightlies)注意TTL 会影响正确性清理太早可能把还会来的迟到数据当成“新 key”一般需要结合业务延迟/乱序程度来定。8. 进阶Window Deduplication每个窗口内去重如果你需要“每个窗口内按 key 去重”例如 10 分钟内同一用户只保留最后一次点击Flink 还有专门的Window Deduplication形态同样要求ORDER BY是时间属性且rownum 1/1/2这种固定谓词才能让优化器识别。(Apache Nightlies)9. 一页避坑清单最常见 5 个坑rownum 1写错/写丢 → 优化器可能无法识别为 Deduplication。(Apache Nightlies)ORDER BY不是时间属性 → 不符合 Deduplication 语义要求。(Apache Nightlies)用 processing time 去重却要求结果稳定 → 可能每次跑都不一样。(Ververica 文檔)下游不支持更新流append-only sink→ 结果不正确或写入失败。(Confluent)不设 TTL/不控状态 → key 越来越多时 state 可能持续膨胀。(Apache Nightlies)