宽表关联订单和订单明细,SQL 里只写了 WHERE 没写 ON。目标表从 3000 万行变成 9.2 亿行,磁盘一天涨了 400G。乍看像缓存或者权限的锅,追下去往往不是。

EXPLAIN SELECT o.id, d.sku_id
FROM ods_order o JOIN ods_order_detail d
  ON o.order_no = d.order_no
WHERE o.dt = '2026-03-01';

追下去是这么回事:两张表之间没有等值条件,数据库按行数相乘做嵌套循环。订单 300 万乘明细 30 条,输出就是九亿行。执行计划里没有 join 的 key,只有 cartesian product,这一行往往被忽略。

「宽表笛卡尔积」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。

线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。日志级别临时调高可以,记得改回去,长期开着既占磁盘又掩盖真问题。

具体做法是,宽表 SQL 里所有 join 都写显式 ON 条件 禁止只用 where 连接;上线前先 explain 看有没有 Cartesian product;分区表按 dt 加约束 让优化器能裁剪;写入前估一行数 超过阈值直接中止。

验收就看一点,explain 里不再出现 Cartesian product 宽表行数和明细行数在同一量级。

作者 9823189