Я знаю, что могу изменить способ выполнения 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 секунды (без использования 10 000 строк).
Однако это не изящное решение, потому что этот запрос является упрощенным примером. В реальном мире я присоединяюсь от c к другим таблицам. Поскольку HAVING
- это фильтр, который выполняется по всему результату, это означало бы, что я вытащил бы некоторые магниты больше записей из db, чем nescessary.
Edit2: Только некоторая информация:
- переменной в этом запросе является c.itemid. Все остальное - фиксированные значения, которые не изменяются.
- Индексы настроены отлично, а mysql выбирает нужные для меня
- между a и b существует отношение 1: n (используется индекс PRIMARY)
- между b и c существует отношение many to many (используется индекс IDX_ITEMID)
точка в том, что mysql должен начать запрашивать таблицу a и работать с ней до c, а не наоборот. Любое изменение для этого.
Решение: Не совсем то, что я хотел, но это, похоже, работает:
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)