mysql 5.7及更早版本不支持视图中使用内联视图(derived table)或相关子查询,报错error 1349;标量子查询会逐行执行导致性能暴增,且select *使优化器失效、元数据不固化引发静默错位。

MySQL 5.7 及更早版本会直接创建失败
视图定义里写 SELECT * FROM (SELECT id, name FROM users) AS t 这种内联视图(derived table),在 MySQL 5.7 及之前版本会报错:ERROR 1349 (HY000): View's SELECT contains a subquery in the FROM clause。这不是语法不规范,而是引擎根本不支持解析该结构。MySQL 8.0+ 才修复此限制,但大量生产环境仍跑着 5.7,贸然使用等于放弃兼容性。
标量子查询会导致每行触发一次执行
像 (SELECT COUNT(*) FROM orders WHERE orders.user_id = users.id) 这类放在 SELECT 列里的相关子查询,语义上要求对 users 表每一行都单独执行一次。如果用户表有 10 万行,订单子查询就被执行 10 万次——哪怕你最终只 WHERE users.status = 'premium' 取 100 行,也拦不住这 10 万次扫描。
- 无法下推外层过滤条件(如
WHERE、LIMIT)到子查询内部 -
ORDER BY和GROUP BY对子查询无影响,它始终是“逐行求值”模式 - 用
EXPLAIN看执行计划时,rows值会暴增,Extra字段常出现Using temporary
SELECT * 在子查询中会让优化器彻底失能
子查询里写 SELECT * 不是“多读几列”的问题,而是让数据库在编译阶段无法确认列集合:它不知道你要哪几列、类型是否匹配、索引能否覆盖。结果就是:
- 谓词下推(Predicate Pushdown)失效:外层
WHERE status = 'paid'无法穿透进子查询去走索引 - 覆盖索引被绕过:哪怕你只取
amount,SELECT *也让优化器认为可能需要整行,强制回表 - 列宽估算严重失真:PostgreSQL 的
subquery_scan节点width值虚高,成本模型误判,选错连接顺序
视图字段结构会随源表变更而静默错位
视图不固化元数据,只存 SQL 文本。一旦你在子查询里用了 SELECT *,后续对源表 ALTER TABLE ADD COLUMN updated_at DATETIME,视图输出就自动多出一列——但列名、列序、甚至类型都可能和下游应用预期不符。
- BI 工具按列名映射字段,突然多一列或列序变动,报表直接空值或错位
- Java 用
ResultSet.getObject(2)按位置取值,新字段插入中间后,取到的就是完全无关的数据 - ORM 如 MyBatis 的
resultMap绑定失效,字段值被错映射到错误属性上
这种问题往往不报错,只在业务逻辑跑偏几天后才被发现。











