mor*_*ebi 3 mysql join on-clause
我有多个连接,包括mysql中的左连接.有两种方法可以做到这一点.
我可以在每次加入后立即设置"ON"条件:
select*from A join B ON(A.bid = B.ID)join C ON(B.cid = C.ID)join D ON(c.did = D.ID)
我可以将它们全部放在一个"ON"子句中:
select*from A join B join C join D ON(A.bid = B.ID AND B.cid = C.ID AND c.did = D.ID)
哪种方式更好?
如果我在查询中需要左连接或右连接,它是否不同?
对于简单的用途,MySQL几乎不可避免地以相同的方式执行它们,因此它是一种偏好和可读性(这是一个很好的辩论主题).
但是,对于更复杂的查询,特别OUTER JOIN是具有可能成为磁盘和io绑定的s的聚合查询- 在不使用带有OUTER JOIN查询的WHERE子句时可能会有性能和看不见的含义.
运行8分钟或.8秒的查询之间的差异可能最终取决于WHERE子句,特别是因为它与索引有关(MySQL如何使用索引):该WHERE子句是向查询优化器提供所需信息的核心部分做它的工作并告诉引擎如何以最有效的方式执行查询.
"本节讨论了处理WHERE子句时可以进行的优化...通过尝试所有可能性来找到加入表的最佳连接组合.如果ORDER BY和GROUP BY子句中的所有列都来自同一个表,那么该表是加入时首选首选."
对于连接中的每个表,构造一个更简单的WHERE来获得对表的快速WHERE评估,并且还尽快跳过行
一些例子:
全表扫描(类型= ALL)Using where,EXTRA中为NO
[SQL] SELECT cr.id,cr2.role FROM CReportsAL cr
LEFT JOIN CReportsCA cr2
ON cr.id = cr2.id AND cr.role = cr2.role AND cr.util = 1000
[Err] Out of memory
Run Code Online (Sandbox Code Playgroud)
用于where优化结果,索引(Using where,Using index):
[SQL] SELECT cr.id,cr2.role FROM CReportsAL cr
LEFT JOIN CReportsCA cr2
ON cr.id = cr2.id
WHERE cr.role = cr2.role
AND cr.util = 1000
515661 rows in set (0.124s)
Run Code Online (Sandbox Code Playgroud)
****ON/WHERE的组合 - 相同的结果 - EXPLAIN*******中的相同计划
[SQL] SELECT cr.id,cr2.role FROM CReportsAL cr
LEFT JOIN CReportsCA cr2
ON cr.id = cr2.id
AND cr.role = cr2.role
WHERE cr.util = 1000
515661 rows in set (0.121s)
Run Code Online (Sandbox Code Playgroud)
MySQL通常足够聪明,能够找出如上所述的简单查询,并且会以类似的方式执行它们,但在某些情况下它不会.
外连接查询性能:
由于LEFT JOIN和RIGHT JOIN都是OUTER JOINS(这里有很好的深入评论),因此产生了笛卡尔积的问题,必须避免使用表扫描,以便尽可能快地消除查询所需的尽可能多的行尽可能.
WHERE一起使用索引和查询优化可以与像集合函数小心使用时完全消除由笛卡尔积造成的问题AVERAGE,GROUP BY,SUM,DISTINCT在运行时间降低的大小的等订单与正确的索引由WHERE的用户和利用实现条款.
最后
同样,对于大多数查询,查询优化器将以相同的方式执行它们 - 使其成为一种偏好方式,但是当查询优化变得重要时,它WHERE是一个非常重要的工具.我已经看到在某些情况下INNER JOIN通过将索引col作为附加的ON..AND ON子句指定一些性能提升,但我无法告诉你原因.