Согласно главе 9 («Анализатор и оптимизатор»), страница 172 книги Саша Пачева «Понимание внутренних функций MySQL»
Вот разбивка оценки запроса на следующие задачи:
- Определите, какие ключи можно использовать для извлечения записей из таблиц, и выберите лучший для каждой таблицы.
- Для каждой таблицы определите, лучше ли сканирование таблицы, чем чтение по ключу. Если имеется много записей, соответствующих значению ключа, преимущества ключа уменьшаются, и сканирование таблицы становится быстрее.
- Определите порядок объединения таблиц, когда в запросе присутствует более одной таблицы.
- Перепишите предложения WHERE, чтобы устранить мертвый код, сократив ненужные вычисления и по возможности изменив ограничения, чтобы открыть путь для использования ключей.
- Исключите неиспользуемые таблицы из объединения.
- Определите, можно ли использовать ключи для
ORDER BY
и GROUP BY
.
- Попытайтесь упростить подзапросы, а также определить, в какой степени их результаты могут быть кэшированы.
- Объединить представления (разверните ссылку на представление как макрос)
На той же странице написано следующее:
В терминологии оптимизатора MySQL каждый запрос представляет собой набор соединений. Термин « соединение» используется здесь более широко, чем в командах SQL. Запрос только к одной таблице является вырожденным соединением. Хотя мы обычно не рассматриваем чтение записей из одной таблицы как объединение, те же структуры и алгоритмы, которые используются с обычными объединениями, прекрасно работают для разрешения запроса только с одной таблицей.
Эпилог
Из-за присутствия ключей, объема данных и выражения запроса, MySQL Joins может иногда делать что-то для нашего же блага (или чтобы получить ответ), и получать результаты, которые мы не ожидали и не можем быстро объяснить.
Я писал об этой причудливости раньше
потому что MySQL Query Optimizer может заставить отклонить определенные ключи во время оценки запроса.
@ Комментарий Фила поможет мне увидеть, как опубликовать этот ответ (+1 за комментарий Фила)
Комментарий @ ypercube (+1 к этому тоже) - это компактная версия моего поста, потому что Оптимизатор запросов MySQL примитивен. К сожалению, так должно быть, поскольку он имеет дело с внешними механизмами хранения.
ВЫВОД
Что касается вашего фактического вопроса, MySQL Query Optimizer будет определять показатели производительности каждого запроса, когда он будет выполнен
- подсчет строк
- выбирая ключи
- массируя прерывистые наборы результатов
- О, да, делая фактическое присоединение
Вам, вероятно, придется навести порядок выполнения, переписав (рефакторинг) запрос
Вот первый запрос, который вы дали
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
where b.tag = 'Y';
Попробуйте переписать его, чтобы сначала оценить ГДЕ
select count(*)
from table1 a
join (select key_col from table2 where tag='Y') b
on b.key_col=a.key_col;
Это определенно изменит план EXPLAIN. Это может привести к лучшим или худшим результатам.
Однажды я ответил на вопрос в StackOverflow, где я применил эту технику. Объяснение было ужасным, но представление было динамитом. Это работало только из-за наличия правильных индексов и использования LIMIT в подзапросе .
Как и в случае с ценами на акции, когда речь идет о запросах и их попытках выразить, применяются ограничения, результаты могут отличаться, а прошлые результаты не свидетельствуют о будущих результатах.