内部连接的慢 where 子句

Posted

技术标签:

【中文标题】内部连接的慢 where 子句【英文标题】:Slow where clause on inner join 【发布时间】:2014-08-15 20:46:20 【问题描述】:
SELECT journey.id
FROM journey
JOIN journey_day ON journey_day.journey = journey.id
JOIN service ON journey.service = service.id
JOIN operator ON operator.id = service.operator
JOIN pattern ON pattern.id = journey.pattern
JOIN pattern_link pl ON pl.section = pattern.section AND pl.from_stop = "370023292"
JOIN pattern_link pl2 ON pl2.section = pl.section AND pl2.from_sequence < pl.from_sequence
WHERE CURDATE() BETWEEN service.date_start and service.date_end AND operator.id = "TMTL"
Above is an SQL query that takes on average 0.1 - 0.3 seconds to run.

由于某种原因,只要我将AND journey_day.day = 3 附加到 WHERE 子句,它就会将执行时间增加 4 秒。正是出于这个原因,我发布了这个问题。

journey_day 表中的每一列都有某种索引。

id(INT 11) | journey(VARCHAR 128) | day(TINYINT 1)

id 是主键,journey 和 day 列都被索引。表的连接绝对没有问题,但是一旦 WHERE 子句对表提出质疑,执行时间就会增加太多,我不喜欢。

journey_day 表只是用来确定旅程的哪一天。例如,如果旅程在星期三和星期四运行,则旅程的标识符将在旅程列中,然后是 3,在另一行中是相同的,但为 4。

您知道为什么会发生这种巨大的执行时间延迟吗?

查询前的 EXPLAIN 结果:http://i.imgur.com/QrjZEHy.png

【问题讨论】:

unspecified JOIN 与 mysql 中的 INNER JOIN 相同。 重复***.com/questions/25333497/… 【参考方案1】:

检查有多少已加入或有条件的字段已编入索引。很可能,journey_day.day 没有被索引,这使得对其进行过滤非常慢。

检查查询的一种方法是在其上运行[EXPLAIN][1](在 MySQL 控制台中):

EXPLAIN <yourquery>

它将为您提供有关如何运行查询、要检查多少行以及是否使用相关表中的索引的详细计划。

您还可以做的(可能有帮助但不能保证)是将整个查询包装到一个过滤器中,以便将其应用于第一个查询的结果。

SELECT journey.id FROM (
SELECT journey.id id, journey_day.day jday
FROM journey
JOIN journey_day ON journey_day.journey = journey.id
JOIN service ON journey.service = service.id
JOIN operator ON operator.id = service.operator
JOIN pattern ON pattern.id = journey.pattern
JOIN pattern_link pl ON pl.section = pattern.section AND pl.from_stop = "370023292"
JOIN pattern_link pl2 ON pl2.section = pl.section AND pl2.from_sequence < pl.from_sequence
WHERE CURDATE() BETWEEN service.date_start and service.date_end AND operator.id = "TMTL") qq
WHERE qq.jday=3;

【讨论】:

您的查询的执行时间大约是 10 倍(包装查询)。另外,我列出了问题中的索引,以及 EXPLAIN 查询的结果。两者都没有帮助:( 你能把EXPLAIN的结果贴在这里吗? 好吧,您的解释告诉我们,对于 JOIN 中的大多数表,没有使用索引。这意味着如果您想更快地运行查询,则必须将索引添加到您 JOIN 或过滤的字段。例如,尝试为journey_day.day 列添加索引,看看是否有帮助。 是的,但就像我说的那样,该列上已经有一个索引 EXPLAIN 在任何情况下都不使用这些索引。

以上是关于内部连接的慢 where 子句的主要内容,如果未能解决你的问题,请参考以下文章

内部连接的 SQL where 子句

带有 WHERE 子句的 MySql 内部连接 ​​[关闭]

在 from 子句 *and* where 子句中添加连接条件使查询更快。为啥?

在 Oracle 查询中将连接从 Where 子句移动到 From 子句

内部联接或 WHERE 子句中的 AND 语句之间的区别

mysql IN子句不使用可能的键