前言
如下,INNER JOIN 的条件 B.status = 's' 是写在 ON 后面? 还是 WHERE 后面? 哪个效能更高?
-- 写法 A:条件在 ON 后SELECT A.name FROM A INNER JOIN B ON B.a_id = A.id and B.status = 's'-- 写法 B:连接条件在 ON,过滤条件在 WHERE SELECT A.name FROM A INNER JOIN B ON B.a_id = A.id WHERE B.status = 's'分析
首先,两者的结果是完全一致的,这个没异议。但是效能有差异吗?
很多人认为放到 ON 后面更好,不符合条件的直接关联不到了,不用在 WHERE 判断了。这在逻辑上是非常正确的:"提前过滤掉不符合条件的记录,减少关联计算量"。
但好消息是:现代数据库优化器已经足够聪明,两种写法通常会生成完全相同的执行计划。
对于写法 B,MySQL 优化器会自动进行 条件下推(Condition Pushdown)
-- 你写的SELECT A.name FROM A INNER JOIN B ON B.a_id = A.id WHERE B.status = 's'-- 优化器实际执行的SELECT A.name FROM A INNER JOIN B ON B.a_id = A.id and B.status = 's'不相信的话,您可以通过 EXPLAIN FORMAT=JSON 验证一下,查看执行计划中的 attached_condition 或 filter,你会发现 B.status = 's' 已经被下推到 JOIN 阶段,如下:
真正影响性能的因素
与其纠结 ON vs WHERE,不如关注这些:
A、索引;对表 B 的字段 a_id 和 status 建立联合索引,走好 NLJ算法,这是影响查询最最重要的因素,只要建立了这个索引,可以说怎么写都无所谓了。
B、数据量;如果每条表A 的数据能从表 B 关联到的数据量极大,几亿条,效能也不会太高。
建议的方式
建议 写法B;连接条件放 ON 后,过滤条件放 WHERE 后,这样看起来非常清晰、明了!
SELECT A.name FROM A INNER JOIN B ON B.a_id = A.id WHERE B.status = 's'总结
老版本的 MySQL(< 5.5)不够智能,WHERE 条件可能真的在 JOIN 后才过滤,效能不如直接放到 JOIN 后。但是新版本的MySQL已经非常聪明了,对于效能来说放到哪里都一样了。
考虑到语义的清晰建议 写法B( 连接条件放 ON 后面,过滤条件放 WHERE 后面)。
最后,放哪里都行!要提升效能,还得是从 索引 和 数据量 这两个大头上做文章。
热门跟贴