Я знаю, что могу изменить способ выполнения запроса MySQL с помощью ключевого слова FORCE INDEX (abc)
.Но есть ли способ изменить порядок выполнения?
Мой запрос выглядит так:
SELECT c.*
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1_id
INNER JOIN table3 c ON b.itemid = c.itemid
WHERE a.itemtype = 1
AND a.busy = 1
AND b.something = 0
AND b.acolumn = 2
AND c.itemid = 123456
У меня есть ключ для каждого отношения / ограничения, которое я использую.Если я запускаю объяснение этого утверждения, я вижу, что mysql начинает запрашивать c первым.
id select_type table type
1 SIMPLE c ref
2 SIMPLE b ref
3 SIMPLE a eq_ref
Однако я знаю, что запросы в порядке a -> b -> c
будут быстрее (я это доказал). Есть ли способсказать mysql использовать определенный порядок?
Обновление: так я знаю, что a -> b -> c
быстрее.
Вышеупомянутый запрос занимает 1,9 секунды и возвращает 7 строк.Если я изменю запрос на
SELECT c.*
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1_id
INNER JOIN table3 c ON b.itemid = c.itemid
WHERE a.itemtype = 1
AND a.busy = 1
AND b.something = 0
AND b.acolumn = 2
HAVING c.itemid = 123456
, запрос будет завершен за 0,01 секунды (без необходимости получать 10000 строк).Однако это не элегантное решение, потому что этот запрос является упрощенным примером.В реальном мире у меня есть объединения из c в другие таблицы.* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * [10] * * * * * * * * * * [10] * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *.1024 * Переменная часть в этом запросе - c.itemid.Все остальное - фиксированные значения, которые не меняются.
Индексы настроены нормально, и mysql выбирает для меня правильные
- между a и b, существует отношение 1: n (индекс PRIMARY равениспользуется)
- между b и c существует отношение многие ко многим (используется индекс IDX_ITEMID)
дело в том, что mysql должен начать запрашивать таблицу aи работать это вниз до с, а не наоборот.Любые изменения, чтобы добиться этого.
Решение: Не совсем то, что я хотел, но, похоже, это работает:
SELECT c.*
FROM table1 a
INNER JOIN table2 b ON a.id = b.table1_id
INNER JOIN table3 c ON b.itemid = c.itemid
WHERE a.itemtype = 1
AND a.busy = 1
AND b.something = 0
AND b.acolumn = 2
AND c.itemid = 123456
AND f.id IN (
SELECT DISTINCT table2.id FROM table1
INNER JOIN table2 ON table1.id = table2.table1_id
WHERE table1.itemtype = 1 AND table1.busy = 1)