用create temporary table存中间结果更稳更快,但须规避连接池残留(需显式drop)、engine=memory降级为磁盘表(避免text/blob)、子查询不可引用(须拆步执行)三类问题。

直接用 CREATE TEMPORARY TABLE 存中间结果,比硬塞进一个超长 SQL 里更稳、更快、更好调——但前提是避开连接池残留、引擎退化和子查询引用这三类高频翻车点。
临时表在连接池环境下会“赖着不走”
应用用了连接池(比如 HikariCP、Druid、PDO 持久连接),CREATE TEMPORARY TABLE 建的表不会随逻辑请求结束而销毁,而是留在复用的物理连接里。下一次业务请求如果再执行同名 CREATE TEMPORARY TABLE,就会报错:Table 'temp_user' already exists。
- 每次使用前加
DROP TEMPORARY TABLE IF EXISTS temp_user(注意是TEMPORARY,不是TABLE) - 避免在存储过程中无条件重复建表;改用先
DROP再CREATE的固定流程 - 不要依赖“连接断开就自动清理”的假设——连接池让这个假设失效
ENGINE=MEMORY 不等于全程内存跑,字段类型会强制降级
CREATE TEMPORARY TABLE 默认用 MEMORY 引擎,但只要定义了 TEXT、BLOB 或显式指定 ENGINE=InnoDB,MySQL 就会悄悄把它变成磁盘表(MyISAM 或 InnoDB 临时文件),I/O 开销陡增,性能可能比原 SQL 还差。
- 用
VARCHAR(255)替代TEXT,哪怕只是存日志片段 - 显式写
ENGINE=MEMORY可以明确意图,但得接受它不支持全文索引、外键,且字符串比较默认按utf8mb4_bin(区分大小写) - 若必须用大字段或事务一致性,选
ENGINE=InnoDB,同时确认tmp_table_size和max_heap_table_size足够大,否则仍会溢出到磁盘
不能在子查询或视图里直接引用临时表
这是语法硬限制:SELECT * FROM (SELECT * FROM temp_user) t 一定会报 Table 'temp_user' doesn't exist,哪怕 temp_user 是上一行刚建好的。
- 拆成两步:先
CREATE TEMPORARY TABLE+INSERT ... SELECT,再单独SELECT或JOIN - MySQL 8.0+ 可用 CTE 替代简单场景,例如
WITH tmp AS (SELECT id FROM user WHERE status = 1) SELECT * FROM tmp JOIN order ON ...,但 CTE 无法多次读写,也不能建索引 - 需要反复过滤、聚合或驱动多表连接时,CTE 不顶用,还是得靠临时表
真正难的不是建表那句 SQL,而是想清楚中间结果要不要索引、字段长度怎么压、连接生命周期怎么管——这些细节没对齐,临时表反而会成为性能黑洞。











