MySQL 5.7 JOIN查询WHERE子句优化疑问:两种查询为何性能一致?
MySQL 5.7关联查询的执行计划优化疑问
场景说明
在MySQL 5.7中有两张表table_a和table_b,各含100000条记录,数据示例如下:
id name ----------- 1 name_1 2 name_2 3 name_3 4 name_4 5 name_5 ...
表的DDL定义为:
CREATE TABLE `table_a` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `table_b` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
执行的查询语句
原本期望第二条查询性能更优:
第一条查询:
select SQL_NO_CACHE * from table_a a inner join table_b b on a.name = b.name where a.id between 50000 and 50100;
第二条查询:
select SQL_NO_CACHE * from ( select * from table_a where id between 50000 and 50100 ) a inner join table_b b on a.name = b.name;
预期与实际结果
原以为第一条会先进行100000100000次迭代再过滤结果,后者先过滤table_a得到100条数据再进行100100000次迭代,因此前者性能会远差于后者。但实际两者耗时均为1.5秒,且EXPLAIN结果无实质差异。
解答
MySQL确实对第一条查询做了**谓词下推(Predicate Pushdown)**优化,使其执行逻辑与第二条完全一致。
MySQL的查询优化器会自动调整执行顺序:它不会先做两张表的全表关联,而是优先利用table_a的主键索引快速筛选出id between 50000 and 50100的100条数据,再用这些数据的name字段去关联table_b。这就等价于第二条查询中先通过子查询过滤table_a的逻辑。
另外,由于table_b的name字段没有创建索引,所以关联时需要对table_b做100次全表扫描(对应table_a筛选出的100条数据),这也是两条语句耗时一致的核心原因。
内容的提问来源于stack exchange,提问作者phantomsee
相关产品推荐
相关产品推荐

