视图性能差主因是谓词无法下推,导致全量计算后再过滤;临时表快的关键是建索引且数据只算一次。MySQL/PG默认不支持嵌套视图谓词下推,SQL Server索引视图可解决但限制多。

视图本身不耗性能,但每次查询都重跑底层SQL;临时表首次建表有开销,后续读写快得多——性能差异不在“创建”,而在“复用次数”和“是否支持下推/索引”。
视图慢的根本原因是谓词无法下推
常见错误现象:SELECT * FROM user_active_view WHERE created_at > '2025-01-01' 比直接查基表慢 5 倍以上。这不是视图写得不好,而是优化器没把 WHERE 条件推入视图定义的子查询里,导致先全量计算视图结果(比如扫描千万行用户表),再过滤。
MySQL 和 PostgreSQL 默认对多层嵌套视图不支持谓词下推,尤其含 GROUP BY、JOIN 或窗口函数时;SQL Server 的索引视图(CREATE VIEW WITH SCHEMABINDING + 唯一聚集索引)可避免该问题,但限制极多:不能有 GETDATE()、*、未显式别名的列。
检查方法:
- PostgreSQL 中用
EXPLAIN (VERBOSE) SELECT * FROM view_name,看是否出现SubPlan或Materialize节点 - MySQL 8.0+ 用
EXPLAIN FORMAT=TREE,看是否标记为dependent subquery
临时表快的关键是能建索引,且数据只算一次
临时表真正起效的前提不是“建了”,而是“建完立刻加索引”。没索引的临时表在后续 JOIN 或 WHERE 时,仍会全表扫描——性能可能比视图还差。
实操建议:
- MySQL:
CREATE TEMPORARY TABLE tmp_orders AS SELECT * FROM orders WHERE dt >= '2025-06-01'后,必须补上CREATE INDEX idx_order_id ON tmp_orders(order_id) - PostgreSQL:
CREATE TEMP TABLE tmp_orders ON COMMIT DROP AS SELECT ...,推荐加上ON COMMIT DROP显式控制生命周期 - SQL Server:
SELECT * INTO #orders FROM orders WHERE ...更快,但无法预定义列类型精度;如需严格控制,改用CREATE TABLE #orders (...); INSERT INTO #orders SELECT ...
注意引擎降级:MySQL 的 TEMPORARY TABLE 默认用 MEMORY 引擎,但只要字段含 TEXT、BLOB 或单行超 max_heap_table_size,就会自动落盘到 MyISAM,IO 暴增。
嵌套视图 vs 多步临时表:执行计划复杂度决定谁更稳
当业务逻辑演变成 v_user_daily → v_user_weekly → v_user_monthly 这种链式视图,执行计划极易退化成嵌套子查询套娃,EXPLAIN 都难定位瓶颈点。此时临时表不是“更优”,而是“唯一可控路径”。
容易被忽略的兼容性陷阱:
- MySQL 的
TEMPORARY TABLE不能被子查询引用两次(报错Table 'xxx' doesn't exist),需改用 CTE 或普通表 - PostgreSQL 的临时表默认在事务结束后不删除,而是持续到会话结束;想提前清理,得显式
DROP TABLE - 所有数据库中,视图定义里都不能引用临时表(
CREATE VIEW v_tmp AS SELECT * FROM #t直接报错)
最常被跳过的动作是:建完临时表后忘记加索引,或没验证谓词是否真被下推进视图——这两处不确认,选什么都白搭。


















