视图含 UNION ALL 时谓词基本不会下推,因语义上无法保证等价;ALGORITHM=TEMPTABLE 视图彻底阻断下推;LEFT JOIN 中外层 WHERE 无法安全下推至右表。

视图含 UNION ALL 时谓词基本不会下推
只要视图定义里出现 UNION ALL(尤其还套了 GROUP BY 或聚合函数),优化器几乎必然放弃谓词下推。这不是配置或 hint 能绕过的——语义上无法保证等价:比如两个子查询分别按 agent_id 聚合后合并,外层加 WHERE agent_id = 123 若下推到任一子查询,可能漏掉另一侧本该满足条件的行。
- MySQL 5.6/5.7、openGauss 6.0.1 明确不支持此类下推;PostgreSQL 虽部分支持,但遇到
LATERAL或窗口函数也会退化 -
/*+ PUSH_PRED */这类 hint 在UNION ALL视图中基本被忽略,执行计划里看不到效果 - 典型现象:外层
WHERE看似合理,但EXPLAIN显示QUERY_DES和QUERY_OLD仍全表扫描
ALGORITHM=TEMPTABLE 视图彻底阻断下推路径
用 SHOW CREATE VIEW view_name 查,如果显示 ALGORITHM=TEMPTABLE,说明视图结果会先物化成临时表,之后才对外层 WHERE 过滤。此时底层表结构、索引信息全部丢失,谓词根本无处可推。
- MySQL 默认对含
GROUP BY、DISTINCT、聚合函数、子查询的视图设为TEMPTABLE - 即使显式声明
ALGORITHM=MERGE,MySQL 5.6 等旧版本也可能悄悄降级——得靠EXPLAIN看是否出现<derivedn></derivedn> - 一旦看到
<derivedn></derivedn>,就确认走的是临时表路径,必须重构逻辑,不能依赖 hint 或参数调优
LEFT JOIN 中 WHERE 条件无法安全下推到右表
在视图里写 LEFT JOIN t2 ON t1.id = t2.id AND t2.status = 'active',和外层写 WHERE t2.status = 'active' 完全是两回事。后者在 JOIN 完成后才生效,若下推到 t2 扫描阶段,会破坏 LEFT JOIN 语义(右表无匹配时左表行仍要保留)。
- 优化器只可能把
ON后的等值条件(如t2.status = 'active')下推,且前提是不影响语义 - 外层
WHERE t2.status = 'active'看似能走索引,实际常导致t2全表扫描——因为优化器不敢动 - 若业务真需要过滤右表,应改用
INNER JOIN,或把条件明确挪到ON子句里
真正麻烦的是那些执行计划里“看起来有下推”但 rows_read 或 cop_task 显示没落地的情况。这时候别查 hint 文档,直接拆视图、换 CTE、或者干脆绕开视图直查基础表——谓词下推不是万能开关,而是受制于语义边界的精细博弈。

















