<p>LEFT JOIN可找出new_import中不在old_import里的记录:SELECT n.* FROM new_import n LEFT JOIN old_import o ON n.order_id = o.order_id WHERE o.order_id IS NULL;需确保order_id非空、建索引、字段类型一致。</p>

用 LEFT JOIN 找出新导入的记录
当两批数据分别存于 old_import 和 new_import 表中,且都有唯一标识字段(如 order_id 或 user_key),最直接的方式是用 LEFT JOIN 查 new_import 中不在 old_import 里的行:
SELECT n.* FROM new_import n LEFT JOIN old_import o ON n.order_id = o.order_id WHERE o.order_id IS NULL;
- 这个写法依赖
order_id在两边都非空;如果存在 NULL 值,JOIN条件会失效,得先过滤或用COALESCE统一处理 - 索引必须建在
order_id上,否则大表 JOIN 会极慢——特别是千万级数据时,没索引可能卡住几分钟 - 注意字段名大小写和类型一致:比如一边是
VARCHAR(32),另一边是CHAR(32),隐式转换可能导致索引失效
用 NOT EXISTS 替代 LEFT JOIN 避免重复和 NULL 陷阱
NOT EXISTS 在语义上更贴近“是否存在”,对 NULL 更鲁棒,也天然避免因 new_import 中有重复 order_id 导致的笛卡尔膨胀:
SELECT * FROM new_import n WHERE NOT EXISTS ( SELECT 1 FROM old_import o WHERE o.order_id = n.order_id );
- 不需要担心
old_import.order_id是 NULL,因为子查询里=对 NULL 永远不成立,NOT EXISTS自然跳过 - 如果
new_import本身有重复主键,这个写法仍能返回全部新记录(而LEFT JOIN可能因重复放大结果) - 多数数据库(PostgreSQL、SQL Server、Oracle)对
NOT EXISTS有良好优化;MySQL 5.7+ 也基本持平,但老版本建议加STRAIGHT_JOIN强制驱动表顺序
对比字段值差异时别只看主键
增量不等于“新增”,还包含“变更”。若需识别内容更新(如金额、状态变化),不能只靠主键匹配,得逐字段比对:
SELECT n.order_id, n.amount, o.amount AS old_amount FROM new_import n JOIN old_import o ON n.order_id = o.order_id WHERE n.amount != o.amount OR (n.amount IS NULL) != (o.amount IS NULL);
-
!=无法判断 NULL 是否相等,所以必须显式写出(n.amount IS NULL) != (o.amount IS NULL) - 字段多时手写
WHERE易漏,可先用MD5(CONCAT(...))或TO_JSONB(PostgreSQL)生成摘要再比对,但要注意 NULL 处理和字符集一致性 - 时间字段慎用
!=:比如updated_at带毫秒但源系统精度只到秒,直接比对会误判;建议用DATE_TRUNC('second', updated_at)对齐后再比较
临时表 + ANALYZE 加速大批量比对
当两个表都超百万行,且没有合适索引时,硬跑 JOIN 很可能 OOM 或超时。稳妥做法是:
- 先把关键字段抽成带索引的临时表:
CREATE TEMP TABLE tmp_new AS SELECT order_id, amount, status FROM new_import; CREATE INDEX ON tmp_new(order_id);
- 在 PostgreSQL / SQL Server 中执行
ANALYZE tmp_new,让优化器知道数据分布 - MySQL 用户可用
OPTIMIZE TABLE整理碎片,但更关键是确保tmp_new.order_id是NOT NULL并设为主键或唯一索引 - 避免在
WHERE中对 JOIN 字段做函数操作,例如UPPER(o.order_id) = UPPER(n.order_id)——这会让索引完全失效
实际排查时,最容易被忽略的是时间窗口错位:比如 new_import 包含昨天和今天的数据,但 old_import 只导出到前天 23:59:59,中间差那 1 秒就可能漏掉一批“看似新增实为延迟到达”的记录。得确认两批数据的时间切片逻辑是否对齐。

















