[英]Where is better to put 'on' conditions in multiple joins? (mysql)
我有多个连接,包括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绑定 - 在不使用带有OUTER JOIN查询的WHERE子句时可能会有性能和看不见的含义。
运行8分钟或.8秒的查询之间的差异可能最终取决于WHERE
子句,特别是因为它与索引有关( MySQL如何使用索引 ): WHERE
子句是为查询优化器提供信息的核心部分它需要做它的工作并告诉引擎如何以最有效的方式执行查询。
“本节讨论了处理WHERE子句时可以进行的优化...通过尝试所有可能性来找到加入表的最佳连接组合。如果ORDER BY和GROUP BY子句中的所有列都来自同一个表,那么该表是加入时首选首选。“
对于连接中的每个表,构造一个更简单的WHERE来获得对表的快速WHERE评估,并且还尽快跳过行
一些例子:
全表扫描(类型= ALL),不Using where
EXTRA中的位置
[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
使用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)
**** 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)
MySQL通常足够聪明,能够找出如上所述的简单查询,并且会以类似方式执行它们,但在某些情况下它不会。
外连接查询性能:
由于LEFT JOIN和RIGHT JOIN都是OUTER JOINS( 这里有很好的深入评论) ,因此产生了笛卡尔积的问题,必须避免使用表扫描,以便尽可能快地消除查询所需的尽可能多的行尽可能。
WHERE
,索引和查询优化器一起使用可以完全消除笛卡尔积与小型函数(如AVERAGE
, GROUP BY
, SUM
, DISTINCT
等)一起使用时所带来的问题。运行时间减少的数量级通过适当的索引来实现。用户和WHERE子句的使用。
最后
同样,对于大多数查询,查询优化器将以相同的方式执行这些 - 使其成为一种偏好方式,但是当查询优化变得重要时, WHERE
是一个非常重要的工具。 通过将索引col指定为附加的ON..AND ON子句,我已经看到在某些情况下使用INNER JOIN
会有一些性能提升,但我无法告诉您原因。
将ON子句与它适用的JOIN放在一起。
原因是:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.