非常慢的MySQL查询列已正确索引

时间:2014-08-22 09:47:02

标签: mysql sql innodb explain

SELECT DISTINCT journey.id, line.name AS line, getDestination(pattern.section) AS destination, TIME_FORMAT(ADDTIME(journey.departure, SEC_TO_TIME(SUM(pl2.time))), '%H:%i') AS departure, operator.code AS operator, bus.registration
FROM journey
INNER JOIN journey_day ON journey_day.journey = journey.id
INNER JOIN service ON service.id = journey.service
INNER JOIN operator ON operator.id = service.operator
INNER JOIN line ON line.service = service.id
INNER JOIN pattern ON pattern.id = journey.pattern
INNER JOIN pattern_link pl ON pl.section = pattern.section AND pl.from_stop = :stop
INNER JOIN pattern_link pl2 ON pl2.section = pattern.section AND pl2.sequence < pl.sequence
LEFT JOIN findmybus.bus ON bus.journey_id = journey.id
WHERE journey_day.day = :day AND CURDATE() BETWEEN service.date_start and service.date_end AND operator.id = :operator
GROUP BY journey.id, journey.departure
HAVING (TIME_TO_SEC(journey.departure) + SUM(pl2.time)) < 86400

以下是查询前面的EXPLAIN语句的结果:

enter image description here

为什么这个查询这么慢?我已经为ON子句中连接的所有列添加了索引。似乎它们并非全部被使用,为什么会这样呢?

查询结果:enter image description here

1 个答案:

答案 0 :(得分:0)

关于使用索引:当您访问一小部分数据时,这会付费。通过查看您的查询,我会猜到dbms以journey_day表开头。该表中可能有数千天,因此将其限制在某一特定日期应该会从表中选择一小部分。

但是,那将是多少次旅行,或者更准确地说:旅程表的相关百分比是多少? dbms必须估计这个以决定是否支持索引使用。这适用于每一张桌子。

可以尝试通过将journey_day标准移动到exists子句来加快速度,但说实话,我不希望这会有多大帮助。正如您已经在做的那样,只需加入MySql通常是最好的。无论如何,为什么不试试呢?

SELECT DISTINCT 
  journey.id, 
  GROUP_CONCAT(line.name) AS lines,
  getDestination(pattern.section) AS destination,
  TIME_FORMAT(ADDTIME(journey.departure, SEC_TO_TIME(SUM(pl2.time))), '%H:%i') AS departure, 
  operator.code AS operator, 
  GROUP_CONCAT(bus.registration) as registrations
FROM journey
INNER JOIN service ON service.id = journey.service AND CURDATE() BETWEEN service.date_start and service.date_end
INNER JOIN operator ON operator.id = service.operator AND operator.id = :operator
INNER JOIN line ON line.service = service.id
INNER JOIN pattern ON pattern.id = journey.pattern
INNER JOIN pattern_link pl ON pl.section = pattern.section AND pl.from_stop = :stop
INNER JOIN pattern_link pl2 ON pl2.section = pattern.section AND pl2.sequence < pl.sequence
LEFT JOIN findmybus.bus ON bus.journey_id = journey.id
WHERE EXISTS
(
  SELECT *
  FROM journey_day 
  WHERE journey_day.journey = journey.id 
  AND journey_day.day = :day
)
GROUP BY journey.id
HAVING (TIME_TO_SEC(journey.departure) + SUM(pl2.time)) < 86400;
相关问题