临时表+join比where in快,因后者将数万id塞入单条sql导致解析、绑定和执行计划生成过重,前者通过物理表结构支持索引嵌套循环(ref/eq_ref),避免全表扫描和参数膨胀。

临时表 + JOIN 更新比 WHERE IN 快的根本原因
因为 WHERE id IN (1,2,3,...,50000) 本质是把 5 万 ID 塞进一条 SQL,MySQL 解析、参数绑定、执行计划生成全变重;而临时表把数据“落地”成物理结构,让优化器能走 ref 或 eq_ref 索引查找,避免全表扫描和参数膨胀。
建临时表时最容易漏掉的三件事
临时表不是建完就能快——漏掉任何一项都会退化为全表扫描:
-
CREATE TEMPORARY TABLE后必须显式加主键或唯一索引,比如id BIGINT PRIMARY KEY;不加就可能触发笛卡尔积 - 目标表的关联字段(如
users.id)也得有索引,否则UPDATE ... JOIN还是扫全表 - 别用
CREATE TEMPORARY TABLE AS SELECT直接建表——它不支持PRIMARY KEY语法糖,列类型也可能隐式变成VARBINARY,导致后续JOIN失败
MySQL 和 SQL Server 的临时表写法差异
同一套逻辑,在不同数据库里写法差很多,抄错就报错:
- MySQL:用
CREATE TEMPORARY TABLE tmp (...) ENGINE=InnoDB,然后UPDATE t1 JOIN tmp ON t1.id = tmp.id SET ... - SQL Server:本地临时表名带单个
#,比如#tmp,更新必须用FROM语法:UPDATE t1 SET t1.status = t2.new_status FROM users t1 JOIN #tmp t2 ON t1.id = t2.id - PostgreSQL:要用
SELECT ... INTO TEMP TABLE tmp,且INTO必须放在SELECT末尾,顺序错直接报syntax error at or near "INTO"
临时表生命周期和事务边界要分清
临时表绑定的是会话(session),不是事务(transaction)——这是很多人卡住的关键点:
- 在事务里创建临时表后,即使
ROLLBACK,临时表依然存在;但断开连接就自动销毁,不用DROP TEMPORARY TABLE - 别指望跨事务复用同一个临时表:事务提交后临时表还在,但下个事务里你得重新
INSERT数据,不能依赖上个事务写入的内容 - 如果批量更新要分多批跑,每批都该重建临时表,而不是往已有临时表里追加——避免数据残留干扰
WHERE 更慢。











