Есть ли разница в производительности между этими двумя примерами запросов?
Запрос 1:
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
where b.tag = 'Y'
Запрос 2;
select count(*)
from table1 a
join table2 b
on b.key_col=a.key_col
and b.tag = 'Y'
Обратите внимание, единственное отличие заключается в размещении дополнительного условия; первый использует WHERE
предложение, а второй добавляет условие к ON
предложению.
Когда я выполняю эти запросы в моей системе Teradata, планы объяснения идентичны, и шаг СОЕДИНЕНИЕ показывает дополнительное условие в каждом случае. Тем не менее, на этот вопрос SO, касающийся MySQL, один из ответов предположил, что второй стиль предпочтительнее, потому что WHERE
обработка происходит после создания соединений.
Есть ли общее правило, которому нужно следовать при кодировании таких запросов? Я предполагаю, что это должно зависеть от платформы, поскольку это, очевидно, не имеет значения для моей базы данных, но, возможно, это просто особенность Teradata. И если это платформа зависит, я бы очень хотел , чтобы получить несколько ссылок документации; Я действительно не знаю, что искать.
источник
Ответы:
Согласно главе 9 («Анализатор и оптимизатор»), страница 172 книги Саша Пачева «Понимание внутренних функций MySQL»
Вот разбивка оценки запроса на следующие задачи:
ORDER BY
иGROUP BY
.На той же странице написано следующее:
Эпилог
Из-за присутствия ключей, объема данных и выражения запроса, MySQL Joins может иногда делать что-то для нашего же блага (или чтобы получить ответ), и получать результаты, которые мы не ожидали и не можем быстро объяснить.
Я писал об этой причудливости раньше
Jan 23, 2013
: Проблема с вложенными запросами UPDATEFeb 22, 2011
: Проблема с подзапросом MySQLпотому что MySQL Query Optimizer может заставить отклонить определенные ключи во время оценки запроса.
@ Комментарий Фила поможет мне увидеть, как опубликовать этот ответ (+1 за комментарий Фила)
Комментарий @ ypercube (+1 к этому тоже) - это компактная версия моего поста, потому что Оптимизатор запросов MySQL примитивен. К сожалению, так должно быть, поскольку он имеет дело с внешними механизмами хранения.
ВЫВОД
Что касается вашего фактического вопроса, MySQL Query Optimizer будет определять показатели производительности каждого запроса, когда он будет выполнен
Вам, вероятно, придется навести порядок выполнения, переписав (рефакторинг) запрос
Вот первый запрос, который вы дали
Попробуйте переписать его, чтобы сначала оценить ГДЕ
Это определенно изменит план EXPLAIN. Это может привести к лучшим или худшим результатам.
Однажды я ответил на вопрос в StackOverflow, где я применил эту технику. Объяснение было ужасным, но представление было динамитом. Это работало только из-за наличия правильных индексов и использования LIMIT в подзапросе .
Как и в случае с ценами на акции, когда речь идет о запросах и их попытках выразить, применяются ограничения, результаты могут отличаться, а прошлые результаты не свидетельствуют о будущих результатах.
источник
Для Oracle, поскольку у MySQL было длинное описание, у нас есть 2 высокоуровневых способа использования оптимизатора.
Во-первых, это оптимизация на основе правил (или RBO). У Oracle есть 15 установленных правил, которые каждый синтаксический запрос пытается выполнить в установленном порядке. Если он не может сгенерировать оптимизированный запрос из правила 1, он переходит к правилу 2 и далее, пока не достигнет правила 15.
для получения дополнительной информации: https://docs.oracle.com/cd/B10500_01/server.920/a96533/rbo.htm
Они влияют на ядра СУБД Oracle версии 11.1 и ниже, которые не были преобразованы в оптимизатор на основе затрат (он же CBO). Oracle 11.2 и выше требуют оптимизатора CBO, но могут принудительно оптимизировать определенные идентификаторы Sql в старом методе RBO, если пользователь хочет.
Вместо этого CBO для Oracle 11.1+ составляет несколько планов выполнения для одного и того же идентификатора SQL и выполняет план с наименьшей общей ожидаемой стоимостью. Он использует большую часть логики RBO, но анализирует статистику таблиц, чтобы создать динамический план затрат на выполнение для каждой операции, которую БД должна выполнить, чтобы предоставить конечному пользователю свои данные. Выполнение полного сканирования таблицы на очень больших таблицах действительно дорого; Выполнение полного сканирования таблицы на таблице с 10 строками - это дешево. В РБО это считалось равными операциями.
для получения дополнительной информации: https://oracle-base.com/articles/misc/cost-based-optimizer-and-database-statistics
Для вашего конкретного примера запроса: Oracle, вероятно, проанализирует информацию, чтобы составить другие планы выполнения, и, таким образом, один будет технически лучше другого. Однако это может быть минимальной разницей. Глядя на это, Oracle RBO и CBO хотели бы запрос 1 больше, потому что он выполняет соединение при меньших условиях, а затем отфильтровывает определенный столбец из временной таблицы, которую он создал из соединения.
источник
Если у вас есть два запроса, и вы думаете, что они эквивалентны, то может произойти следующее:
Есть разные планы выполнения. У нас есть два случая здесь.
2.1 Запросы имеют разные планы выполнения, но оба плана работают одинаково хорошо. Это тоже хорошо. Нет необходимости, чтобы для эквивалентных запросов создавался один и тот же план. Но производительность должна быть равной. И снова мы надеемся, что это самое лучшее.
2.2 Запросы имеют разные планы выполнения, и один план лучше другого. Опять у нас есть подсистемы:
2.2.1 Планы отличаются, потому что запросы не эквивалентны. Поэтому внимательно проверьте, действительно ли они эквивалентны. В вашем случае они действительно эквивалентны.
2.2.2 Планы разные, но запросы эквивалентны. Это означает, что оптимизатор не достаточно зрелый. В идеальном мире с идеальными оптимизаторами этого не должно быть. Так что да, это зависит от платформы, и вы должны изучить конкретные документы платформы, чтобы выяснить, почему это происходит.
2.2.3 Планы разные, запросы эквивалентны, в программном обеспечении базы данных есть ошибка.
источник