简体   繁体   中英

Slow where clause on inner join

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.

For some reason, as soon as a I append AND journey_day.day = 3 to the WHERE clause it adds an extra 4 seconds to the execution time. It is for this reason that I am posting this question.

Every column in the journey_day table has indexing of some sort.

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

The id is the primary key, the journey and day columns are both indexed. The table is joined with absolutely no problems, but as soon as the WHERE clause questions the table, execution time goes up by far too much for my liking.

The journey_day table is just there to determine which day the journey runs on. For example, if a journey runs on Wednesday and Thursdays, the journey would have its identifier in the journey column and then 3, same thing in another row but with 4.

Any ideas why this huge delay in execution time is happening?

Result of an EXPLAIN prepended to the query: http://i.imgur.com/QrjZEHy.png

Check how many of the fields which are JOINed or conditioned, are indexed. Most possibly, journey_day.day is not indexed, which makes filtering on it quite slow.

One of the ways to check your query is to run [EXPLAIN][1] on it (in MySQL console):

EXPLAIN <yourquery>

It will give you detailed plan of how your query is run, how many rows are going to be checked and whether it uses indexes from the related tables.

What you can also do (which might help but not guaranteed) is wrap your whole query into that one filter, so that you apply it to the result of the first query.

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM