SELECT DISTINCT(journey.id), line.name, journey.departure
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 = "370023292"
INNER JOIN pattern_link pl2 ON pl2.section = pattern.section AND pl2.from_sequence < pl.from_sequence
WHERE journey_day.day = 1 AND CURDATE() BETWEEN service.date_start and service.date_end AND operator.id = "TMTL"
ORDER BY journey.departure

Выше представлен запрос MySQL, выполнение которого занимает приблизительно 0,05 секунды.

Как только я добавляю этот LEFT JOIN journey_code ON journey_code.journey = journey.id, он добавляет к запросу еще 4-6 секунд. Я считаю, что это как-то связано со второй ссылкой на столбец journey.id в предложении ON. Почему это LEFT JOIN так сильно задерживает результаты запроса?

Информация о таблице journey_code:

id(INT 11 PK AI) | journey(VARCHAR 128) | code(VARCHAR 16)

И journey, и code имеют индексы. Я пробовал составной индекс для двух, и это никоим образом не ускорило запрос.

Результат добавления EXPLAIN к запросу: http://i.imgur.com/BVrm9qv .png

Есть идеи, почему это происходит?

0
jskidd3 16 Авг 2014 в 16:39
Пожалуйста, добавьте результат EXPLAIN к вашему вопросу.
 – 
VMai
16 Авг 2014 в 16:41
Конечно, я добавлю это сейчас. Пожалуйста, потерпите 1 минуту.
 – 
jskidd3
16 Авг 2014 в 16:41
Я обновил вопрос, добавив EXPLAIN
 – 
jskidd3
16 Авг 2014 в 16:43
Вы серьезно присоединяетесь к 8 столам?
 – 
TJ-
16 Авг 2014 в 16:45
Какая альтернатива? Вы раньше не присоединялись к нескольким столам? Тот факт, что для присоединения к 7 таблицам требуется 0,05 секунды, и 6 секунд для присоединения к 8 таблицам, не говорит вам, что что-то может быть не так с объединением на последней таблице?
 – 
jskidd3
16 Авг 2014 в 16:46

1 ответ

Лучший ответ

Попробуйте превратить указанный выше запрос в подзапрос:

SELECT j.*, jc.<whatever>
FROM (SELECT DISTINCT journey.id, line.name, journey.departure
      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 = "370023292"
      INNER JOIN pattern_link pl2 ON pl2.section = pattern.section AND pl2.from_sequence < pl.from_sequence
      WHERE journey_day.day = 1 AND
            CURDATE() BETWEEN service.date_start and service.date_end AND
            operator.id = 'TMTL'
    ) j left join
    journey_code jc
    ON jc.journey = j.id
ORDER BY j.departure

Как работает MySQL, он должен запустить подзапрос и материализовать его. Если у вас есть индекс по journey_code(journey), соединение должно быть быстрым.

1
Gordon Linoff 16 Авг 2014 в 16:55
Спасибо, Гордон, я попробую это через минуту и ​​дам знать, если это улучшение
 – 
jskidd3
16 Авг 2014 в 17:02
Абсолютно фантастично! Большое спасибо, это работает мечта! 12-часовое расследование подошло к концу 8-)
 – 
jskidd3
16 Авг 2014 в 17:14