MySQL是否会跳过未使用关联的连接?含子查询与左连接场景
MySQL关联优化与视图性能问题解答
因为外键约束和主键的存在,以下两个查询是等价的:
CREATE TABLE customers ( id int PRIMARY KEY ); CREATE TABLE orders ( id int, customer_id int ); ALTER TABLE orders ADD FOREIGN KEY (customer_id) REFERENCES customers(id); SELECT id , (SELECT 1 FROM customers c WHERE c.id = o.id) one FROM orders o; SELECT o.id , 1 one FROM orders o JOIN customers c ON c.id = o.customer_id;
这两个查询中,orders表的每一行都会在结果集中对应一行。如果这两个查询作为子查询,且外部查询没有使用one列,理论上可以跳过关联操作。
针对你的问题,解答如下:
1. MySQL是否能在两种场景下都跳过关联?
可以,尤其是MySQL 8.0及以上版本的优化器具备这个能力:
- 对于内关联写法:优化器能识别外键约束保证
customer_id必然匹配customers.id,且查询未用到customers表的任何列,会直接跳过关联,只扫描orders表。 - 对于标量子查询写法:优化器会发现子查询的结果列未被引用,再结合外键约束确认子查询一定返回1,因此会直接忽略该子查询,不访问
customers表。
2. 换成NULL列和LEFT JOIN的情况
如果改成以下这类写法:
-- LEFT JOIN写法 SELECT o.id , NULL AS col FROM orders o LEFT JOIN customers c ON c.id = o.customer_id; -- 标量子查询返回NULL SELECT id , (SELECT NULL FROM customers c WHERE c.id = o.id) col FROM orders o;
只要外部查询不使用col列,优化器同样会跳过关联或子查询。因为LEFT JOIN不影响主表行的返回,且未用到关联表的列,优化器会简化查询,只处理orders表。但要注意:如果LEFT JOIN的条件涉及customers表的非主键列,或者没有外键约束,优化器可能无法完成这个简化。
3. 反规范化视图的高效写法建议
- 只保留必要列:视图中只包含报表实际需要的列,避免冗余列引发不必要的关联或计算。
- 完善约束关系:确保表之间的外键、主键约束完整,让优化器能识别关联的必然性,从而做查询简化。
- 替换冗余关联:如果视图中的关联只是为了生成固定值(比如示例中的
1),直接写固定值而非关联表,减少优化器的判断成本。 - 考虑物化视图:MySQL 8.0.19及以上支持物化视图,可预先计算并存储视图结果,避免每次查询都重新计算,适合大型报表场景(注意设置合适的刷新策略保证数据一致)。
- 验证执行计划:创建视图后用
EXPLAIN查看执行计划,确认优化器是否跳过了不必要的关联,若未达到预期,调整视图写法。
内容的提问来源于stack exchange,提问作者William Entriken
相关产品推荐
相关产品推荐

