Предположим, у меня три таблицы - пользователи, серверы и платежи. Каждый пользователь может иметь несколько серверов, и каждый сервер может иметь несколько платежей. Давайте также скажем, что я хотел найти самые последние платежи и получить информацию о серверах/клиентах, к которым прилагаются эти платежи. Вот запрос, который мог бы сделать это:СОБЫТИЯ, выполняемые в странном порядке; испортить ORDER BY?
SELECT *
FROM payments p
JOIN customers c ON p.custID = c.custID
JOIN servers s ON s.serverID = p.serverID
WHERE c.hold = 0
AND c.archive = 0
ORDER BY p.paymentID DESC
LIMIT 10;
Проблема заключается в том, что, когда я бегу EXPLAIN на этот запрос я получаю это:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE c ref PRIMARY,hold_archive hold_archive 3 const,const 28728 Using where; Using index; Using temporary; Using filesort
1 SIMPLE p ref custID custID 5 customers.custID 3 Using where
1 SIMPLE s eq_ref PRIMARY PRIMARY 4 payments.serverID 1 Using index
Проблема заключается в том, что запрос занимает некоторое время для запуска. Если я удалю ORDER BY, он станет на 10x быстрее. Но мне нужен ORDER BY. Вот EXPLAIN, когда я удаляю ORDER BY:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE c ref PRIMARY,hold_archive hold_archive 3 const,const 28728 Using where; Using index
1 SIMPLE p ref custID custID 5 customers.custID 3 Using where
1 SIMPLE s eq_ref PRIMARY PRIMARY 4 payments.serverID 1 Using index
Так что большая разница в том, что «Использование временного» и «Использование FileSort» отсутствуют в дополнительной колонке.
Похоже, в этом случае причина в том, что столбец, в котором я выполняю ORDER BY, не является первым столбцом в EXPLAIN.
Другое наблюдение. Если я удалю одно из предложений WHERE (при сохранении ORDER BY), он ускорится схожим образом, но мне нужны оба ГДЕ. Ниже приведен пример того, что EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE p index custID,serverID PRIMARY 4 NULL 10 Using where
1 SIMPLE c eq_ref PRIMARY,hold_archive PRIMARY 4 payments.custID 1 Using where
1 SIMPLE s eq_ref PRIMARY PRIMARY 4 payments.serverID 1 Using index
Здесь ORDER BY столбца/в/делается на первом столбце EXPLAIN. Но почему MySQL переустанавливает порядок, в котором находятся JOINed, и как я могу сделать это, чтобы он этого не делал? Вы можете форсировать индексы в MySQL, но похоже, что это не помогло бы.
Любые идеи?
С такими вопросами вам также необходимо предоставить инструкции SHOW CREATE TABLE для всех соответствующих таблиц. – Strawberry
Быстрое предположение: если нет предложения 'ORDER BY', то сервер возвращает вам грамотно первые 10 записей, которые соответствуют критериям и перестает обрабатываться после достижения этого числа. Вероятно, он начинается с таблицы 'customer', потому что на этом есть фильтр, а затем ищет связанные« платежи », а затем и« серверы », которые соответствуют. Хорошо работает. Однако, когда вы добавляете 'ORDER BY', тогда сначала нужно составить список * all * соответствующих записей (' c' => 'p' =>' s'), сортировать их на 'paymentID' а затем выберите первые 10 из этого списка, начиная с «самого низкого». – deroby