简体   繁体   English

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

[英]Where is better to put 'on' conditions in multiple joins? (mysql)

I have multiple joins including left joins in mysql. 我有多个连接,包括mysql中的左连接。 There are two ways to do that. 有两种方法可以做到这一点。

  1. I can put "ON" conditions right after each join: 我可以在每次加入后立即设置“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) 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. I can put them all in one "ON" clause: 我可以将它们全部放在一个“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) select * from A join B join C join D ON(A.bid = B.ID AND B.cid = C.ID AND c.did = D.ID)

Which way is better? 哪种方式更好?

Is it different if I need Left join or Right join in my query? 如果我在查询中需要左连接右连接 ,它是否不同?

For simple uses MySQL will almost inevitably execute them in the same manner, so it is a manner of preference and readability (which is a great subject of debate). 对于简单的用途,MySQL几乎不可避免地以相同的方式执行它们,因此它是一种偏好和可读性(这是一个很好的辩论主题)。

However with more complex queries, particularly aggregate queries with OUTER JOIN s that have the potential to become disk and io bound - there may be performance and unseen implications in not using a WHERE clause with OUTER JOIN queries. 但是,对于更复杂的查询,尤其是具有OUTER JOIN的聚合查询,这些查询有可能成为磁盘和io绑定 - 在不使用带有OUTER JOIN查询的WHERE子句时可能会有性能和看不见的含义。

The difference between a query that runs for 8 minutes, or .8 seconds may ultimately depend on the WHERE clause, particularly as it relates to indexes ( How MySQL uses Indexes ): The WHERE clause is a core part of providing the query optimizer the information it needs to do it's job and tell the engine how to execute the query in the most efficient way. 运行8分钟或.8秒的查询之间的差异可能最终取决于WHERE子句,特别是因为它与索引有关( MySQL如何使用索引 ): WHERE子句是为查询优化器提供信息的核心部分它需要做它的工作并告诉引擎如何以最有效的方式执行查询。

From How MySQL Optimizes Queries using WHERE : MySQL如何使用WHERE优化查询

"This section discusses optimizations that can be made for processing WHERE clauses...The best join combination for joining the tables is found by trying all possibilities. If all columns in ORDER BY and GROUP BY clauses come from the same table, that table is preferred first when joining." “本节讨论了处理WHERE子句时可以进行的优化...通过尝试所有可能性来找到加入表的最佳连接组合。如果ORDER BY和GROUP BY子句中的所有列都来自同一个表,那么该表是加入时首选首选。“

For each table in a join, a simpler WHERE is constructed to get a fast WHERE evaluation for the table and also to skip rows as soon as possible 对于连接中的每个表,构造一个更简单的WHERE来获得对表的快速WHERE评估,并且还尽快跳过行

Some examples: 一些例子:

Full table scans (type = ALL) with NO Using where in EXTRA 全表扫描(类型= 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

Uses where to optimize results, with index ( Using where , Using index ) : 使用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)

****Combination of ON/WHERE - Same result - Same plan in EXPLAIN ******* **** 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 is typically smart enough to figure out simple queries like the above and will execute them similarly but in certain cases it will not. MySQL通常足够聪明,能够找出如上所述的简单查询,并且会以类似方式执行它们,但在某些情况下它不会。

Outer Join Query Performance: 外连接查询性能:

As both LEFT JOIN and RIGHT JOIN are OUTER JOINS ( Great in depth review here) the issue of the Cartesian product arises, the avoidance of Table Scans must be avoided, so that as many rows as possible not needed for the query are eliminated as fast as possible. 由于LEFT JOIN和RIGHT JOIN都是OUTER JOINS( 这里有很好的深入评论) ,因此产生了笛卡尔积的问题,必须避免使用表扫描,以便尽可能快地消除查询所需的尽可能多的行尽可能。

WHERE , Indexes and the query optimizer used together may completely eliminate the problems posed by cartesian products when used carefully with aggregate functions like AVERAGE , GROUP BY , SUM , DISTINCT etc. orders of magnitude of decrease in run time is achieved with proper indexing by the user and utilization of the WHERE clause. WHERE ,索引和查询优化器一起使用可以完全消除笛卡尔积与小型函数(如AVERAGEGROUP BYSUMDISTINCT等)一起使用时所带来的问题。运行时间减少的数量级通过适当的索引来实现。用户和WHERE子句的使用。

Finally 最后

Again, for the majority of queries, the query optimizer will execute these in the same manner - making it a manner of preference but when query optimization becomes important, WHERE is a very important tool. 同样,对于大多数查询,查询优化器将以相同的方式执行这些 - 使其成为一种偏好方式,但是当查询优化变得重要时, WHERE是一个非常重要的工具。 I have seen some performance increase in certain cases with INNER JOIN by specifying an indexed col as an additional ON..AND ON clause but I could not tell you why. 通过将索引col指定为附加的ON..AND ON子句,我已经看到在某些情况下使用INNER JOIN会有一些性能提升,但我无法告诉您原因。

Put the ON clause with the JOIN it applies to. 将ON子句与它适用的JOIN放在一起。

The reasons are: 原因是:

  • readability: others can easily see how the tables are joined 可读性:其他人可以很容易地看到表格的连接方式
  • performance: if you leave the conditions later in the query, you'll get way more joins happening than need to - it's like putting the conditions in the where clause 性能:如果您稍后在查询中保留条件,您将获得比需要更多的连接 - 这就像将条件放在where子句中
  • convention: by following normal style, your code will be more portable and less likely to encounter problems that may occur with unusual syntax - do what works 约定:通过遵循正常的样式,您的代码将更具可移植性,并且不太可能遇到可能出现的异常语法问题 - 做有效的方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM