视图每次查询重执行底层SQL,临时表首次建表有开销但后续读写更快;性能差异取决于复用次数、谓词下推能力及是否支持索引。

视图本身不耗性能,但每次查询都重跑底层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 都难定位瓶颈点。此时临时表不是“更优”,而是“唯一可控路径”。
- 视图链越深,优化器越可能放弃重写,最终等价于
SELECT * FROM (SELECT * FROM (SELECT ...)),每层都无索引、无统计信息 - 临时表可分步验证:先建
tmp_user_daily,SELECT COUNT(*)确认行数;再建tmp_user_weekly,EXPLAIN ANALYZE查 JOIN 效率 - PostgreSQL 中大量视图会让
pg_views查询变慢,影响元数据操作;临时表完全不计入系统目录 - 不要为“复用”硬套视图:如果某段逻辑只被调用 1–2 次,直接用 CTE 或子查询更轻量;临时表适合被引用 ≥3 次的中间结果
真正容易被忽略的不是语法差异,而是生命周期管理——视图一旦创建就长期存在,依赖关系隐晦;临时表虽“临时”,但忘了 DROP 或没设 ON COMMIT DROP,会在会话中持续占内存或磁盘,尤其在连接池复用场景下,可能引发资源泄漏。


















