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

SQL LEFT JOIN 未使用表 2 中的值填充列

INNER JOIN与LEFT JOIN在SQL Server的性能

SQL sum()后许多字段要group by不使用group by, 改用left join select 需要的字段。哪个方法好?速度快?

SQL中 left join 的底层原理

LINQ to SQL CompiledQuery 变慢