SQL,未使用的 LEFT JOIN 速度变慢,优化器不起作用?
Posted
技术标签:
【中文标题】SQL,未使用的 LEFT JOIN 速度变慢,优化器不起作用?【英文标题】:SQL, Unused LEFT JOINs slowing down, Optimizer not working? 【发布时间】:2017-11-10 21:38:16 【问题描述】:我有一个简单的 SQL 语句。结果集中未使用某些 LEFT JOIN。为什么 mysql 5.5 会减慢我的 SQL 的第二个版本的执行速度,尽管 JOIN 与结果完全无关?为什么不忽略 LEFT JOIN?
执行时间:0.03 秒(无 JOIN)
SELECT SQL_NO_CACHE count(o.orderid), o.orderid
FROM
customerorder o
LIMIT 0,20
执行时间:0.20 秒(不相关的 JOIN)
SELECT SQL_NO_CACHE count(o.orderid), o.orderid
FROM
customerorder o
LEFT JOIN object o1 ON o1.objectid = o.orderid
LEFT JOIN object o2 ON o2.objectid = o1.objectid
LEFT JOIN object o3 ON o3.objectid = o2.objectid
LEFT JOIN object o4 ON o4.objectid = o3.objectid
LEFT JOIN object o5 ON o5.objectid = o4.objectid
LIMIT 0,20
编辑/“解决方案”:它不会被忽略,因为 JOIN 是相关的 :-) 它们可以增加 count()。所以问题的解决方案是这样的:
SELECT SQL_NO_CACHE (select count(*) from customerorder) as count, o.orderid
FROM
customerorder o
left JOIN object o1 ON o1.objectid = o.orderid
left JOIN object o2 ON o2.objectid = o1.objectid
left JOIN object o3 ON o3.objectid = o2.objectid
left JOIN object o4 ON o4.objectid = o3.objectid
left JOIN object o5 ON o5.objectid = o4.objectid
LIMIT 0,20
【问题讨论】:
如果不使用所有 LEFT JOINS 执行查询以查看结果,MySQL 怎么知道 JOINS 与结果完全无关? 难道优化器不应该认识到选中的列与连接的表无关吗? @xsign 好问题,这是执行顺序的问题。见下文。 布赖恩是对的。如果其中一个联接确实解决了,无论您仅从一个表中选择这一事实,它都可能使您的 COUNT 更高。如果没有返回任何内容,O1 到 O 的连接将短路其他连接。 @DanielG 这是一个很好的观点。你认为 MySQL 能够从主键或索引中确定连接会产生 1:1 的查找并且不会打扰吗?以我的经验,它并不那么聪明,但也许幕后的东西比我记得的要多。 【参考方案1】:很简单,查询优化器必须先执行所有连接,然后才会质疑是否需要它们。
注意:正如 JNevill 在下面雄辩地指出,在执行时,某些 RDBMS 系统将首先解析查询,并根据整个查询的上下文评估数据检索机制。避免下面的事件执行过于简单。
执行顺序:
1. FROM clause (JOIN is lumped in here)
2. WHERE clause
3. SELECT clause
4. GROUP BY clause
5. HAVING clause
6. ORDER BY clause
【讨论】:
不太了解这里的反对意见?答案是正确的。 这是一个非常简单的操作顺序,没有考虑优化。虽然,考虑到 MySQL 的完美优化,这可能已经接近了它需要的程度。 @JNevill 可能很简单,但在这种情况下是合适的。 在任何其他 RDBMS(mysql 也不例外)中,实际写入的查询不是在数据库中 1:1 执行的。大多数产品都有一个优化引擎,可以在解析引擎完成其工作后做出有关数据检索的决策。每个其他 RDBMS 都不会打扰 OP 查询中的连接。 MySQL 有点笨,但它可以让你有足够的绳索上吊自己。 有没有机会给优化器一个可以忽略JOIN的提示?以上是关于SQL,未使用的 LEFT JOIN 速度变慢,优化器不起作用?的主要内容,如果未能解决你的问题,请参考以下文章
关于SQL 查询效率问题 left join 改成 inner join union
INNER JOIN与LEFT JOIN在SQL Server的性能
SQL sum()后许多字段要group by不使用group by, 改用left join select 需要的字段。哪个方法好?速度快?