视图本身不存数据,但用得不对性能开销会翻倍甚至失控;核心在于展开后执行计划变差、嵌套过深触发物化、标量函数导致逐行计算、统计信息过时引发误判,以及基表缺失索引被隐蔽掩盖。

直接说结论:视图本身不存数据,但用得不对,性能开销会翻倍甚至失控——核心不是“能不能用”,而是“怎么用”和“在哪用”。
视图查询被展开后执行计划变差
数据库(如 SQL Server、PostgreSQL)查视图时,会把视图定义原样内联进外层查询,再生成最终执行计划。这意味着:视图里写了 SELECT *,哪怕你只取其中 2 列,数据库仍可能扫描所有列;视图里有 JOIN 和 WHERE,外层再加条件,优化器未必能把新条件下推到基表层。
- 嵌套三层以上视图(A → B → C)会让执行计划膨胀,出现多余
Materialize或Spool算子 - 视图定义中含
ORDER BY或DISTINCT,而调用方又没用到排序或去重逻辑,这部分计算白跑 - 用
EXPLAIN (ANALYZE)(PostgreSQL)或“显示实际执行计划”(SQL Server)对比SELECT * FROM v_xxx和直接跑视图 SQL,常发现二者计划不一致
标量函数让整条查询变成逐行计算
只要视图的 SELECT 列表里出现自定义标量函数(比如 dbo.GetYear(order_date)),数据库就必须对结果集每一行都调用一次——哪怕最终只取前 10 行,也得先算完全部行。
- SQL Server 不会对标量 UDF 做内联优化,每次调用都有上下文切换和参数序列化开销
-
WHERE dbo.GetYear(order_date) = 2024会强制全表扫描,order_date上的索引完全失效 - 函数内部含
SELECT、WHILE或字符串拼接时,开销呈指数增长;实测案例中 7 个函数拖慢查询从 0.26 秒到 78 秒 - 函数间若有隐式转换(如
VARCHAR输入进INT返回的函数),还会触发额外类型推导和内存拷贝
统计信息过时让视图“突然变慢”
视图不缓存执行计划,但它的底层表如果长期没更新统计信息,优化器就会基于错误分布做决策——比如该走索引却选了全表扫描,且这种问题在视图上更难察觉。
- 订单表从 500 万行涨到 5000 万行后,原本 200ms 的查询变 5 秒,原因就是统计信息过时
- 自动更新默认阈值(如 SQL Server 的 20% 行变更)在高吞吐场景下常不触发,需手动缩短阈值或设置低峰期全量收集
- 数据倾斜严重列(如用户等级分布极度不均),普通采样统计偏差大,应启用扩展统计信息或直方图
最容易被忽略的一点:视图上建不了索引(除 SQL Server 的索引视图等特例外),所谓“给视图加索引”本质是给底层表加——但很多人连基表字段都没索引,就直接套视图,等于把性能隐患封装得更隐蔽。


















