在多个连接中放置'on'条件哪里更好? (MySQL的)

时间:2013-08-11 05:00:05

标签: mysql join on-clause

我有多个连接,包括mysql中的左连接。有两种方法可以做到这一点。

  1. 我可以把" 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)

  2. 我可以将它们全部放在一起" 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)

  3. 哪种方式更好?

    如果我的查询中需要左连接右连接,会有所不同吗?

2 个答案:

答案 0 :(得分:5)

对于简单的用途,MySQL几乎不可避免地以相同的方式执行它们,因此它是一种偏好和可读性(这是一个很好的辩论主题)。

然而,对于更复杂的查询,特别是具有OUTER JOIN的可能成为磁盘和io绑定的聚合查询 - 在不使用带有OUTER JOIN查询的WHERE子句时可能会有性能和看不见的含义。

运行8分钟或.8秒的查询之间的差异可能最终取决于WHERE子句,特别是因为它与索引(How MySQL uses Indexes)相关:WHERE子句是向查询优化器提供执行工作所需信息的核心部分,并告诉引擎如何以最有效的方式执行查询。

来自How MySQL Optimizes Queries using WHERE

  

“本节讨论可以进行处理的优化   WHERE子句...加入表的最佳连接组合是   通过尝试所有可能性找到。如果ORDER BY和中的所有列   GROUP BY子句来自同一个表,该表是首选   首先加入。“

     

对于连接中的每个表,构造一个更简单的WHERE来获得快速   WHERE评估表,并尽快跳过行   可能

一些例子:

全表扫描(类型=全部),EXTRA中没有Using where

[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 whereUsing 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(Great in depth review here)出现了笛卡尔积的问题,因此必须避免使用表扫描,以便消除查询不需要的尽可能多的行尽可能快。

WHERE,索引和查询优化器一起使用可能完全消除了笛卡儿产品在仔细使用AVERAGEGROUP BY等聚合函数时所带来的问题,SUMDISTINCT等等。通过用户的正确索引和WHERE子句的使用,可以实现运行时间减少的数量级。

<强>最后

同样,对于大多数查询,查询优化器将以相同的方式执行这些 - 使其成为一种偏好方式,但当查询优化变得重要时,WHERE是一个非常重要的工具。通过将索引col指定为附加的ON..AND ON子句,我已经看到INNER JOIN在某些情况下性能有所提高,但我无法告诉您原因。

答案 1 :(得分:3)

将ON子句与它适用的JOIN放在一起。

原因是:

  • 可读性:其他人可以很容易地看到表格的加入方式
  • 性能:如果你稍后在查询中保留条件,你将获得比需要更多的连接 - 这就像把条件放在where子句中
  • 约定:通过遵循正常样式,您的代码将更具可移植性,并且不太可能遇到可能因语法不正常而出现的问题 - 做有效的工作