10.2.1.9 Оптимизация внешних соединений
Внешние соединения включают LEFT JOIN и RIGHT JOIN.
MySQL реализует следующим образом: A LEFT
JOIN B
join_specification
Таблица
Bустанавливается в зависимость от таблицыAи всех таблиц, от которых зависитA.Таблица
Aустанавливается в зависимость от всех таблиц (кромеB), используемых в условииLEFT JOIN.Условие
LEFT JOINиспользуется для определения способа извлечения строк из таблицыB. (Другими словами, любые условия в фрагментеWHEREне используются.)Выполняются все стандартные оптимизации соединений, за исключением того, что таблица всегда считывается после всех таблиц, от которых она зависит. Если есть циклическая зависимость, возникает ошибка.
Выполняются все стандартные
WHEREоптимизации.Если в
Aесть строка, соответствующая условиюWHERE, но нет строки вB, соответствующей условиюON, генерируется дополнительнаяBстрока со всеми столбцами, установленными в значениеNULL.Если вы используете
LEFT JOINдля поиска строк, отсутствующих в некоторой таблице, и у вас есть следующее условие:в частиcol_nameIS NULLWHERE, гдеcol_name— столбец, объявленный какNOT NULL, MySQL прекращает поиск дополнительных строк (для определённой комбинации ключей) после нахождения одной строки, соответствующей условиюLEFT JOIN.
Реализация RIGHT JOIN аналогична реализации LEFT JOIN с перевёрнутыми ролями таблиц. Правые соединения преобразуются в эквивалентные левые соединения, как описано в Разделе 10.2.1.10, «Оптимизация внешних соединений».
Для LEFT JOIN, если условие WHERE всегда ложно для сгенерированной строки NULL, LEFT
JOIN преобразуется во внутреннее соединение. Например, фрагмент WHERE будет ложным в следующем запросе, если t2.column1 было бы NULL:
SELECT * FROM t1 LEFT JOIN t2 ON (column1) WHERE t2.column2=5;
Поэтому, безопасно преобразовать запрос во внутреннее соединение:
SELECT * FROM t1, t2 WHERE t2.column2=5 AND t1.column1=t2.column1;
Тривиальные WHERE условия, возникающие из константных литеральных выражений, удаляются на стадии подготовки, а не на более поздних этапах оптимизации, когда соединения уже были упрощены. Раннее удаление тривиальных условий позволяет оптимизатору преобразовывать внешние соединения во внутренние; это может привести к улучшенным планам для запросов с внешними соединениями, содержащими тривиальные условия в фрагменте WHERE, например, таком:
SELECT * FROM t1 LEFT JOIN t2 ON condition_1 WHERE condition_2 OR 0 = 1
Оптимизатор теперь на стадии подготовки видит, что 0 = 1 всегда ложно, делая OR 0 = 1 избыточным и удаляя его, оставляя это:
SELECT * FROM t1 LEFT JOIN t2 ON condition_1 where condition_2
Теперь оптимизатор может переписать запрос как внутреннее соединение, так:
SELECT * FROM t1 JOIN t2 WHERE condition_1 AND condition_2
Теперь оптимизатор может использовать таблицу t2 перед таблицей t1, если это приведёт к лучшему плану запроса. Для указания порядка соединения таблиц используйте подсказки оптимизатора; см. Раздел 10.9.3, «Подсказки оптимизатора». В качестве альтернативы, используйте STRAIGHT_JOIN; см. Раздел 15.2.13, «Оператор SELECT». Однако, STRAIGHT_JOIN может препятствовать использованию индексов, поскольку он отключает преобразования полусоединений; см. .
© 2025 Oracle
Licensed under the GPLv2 License.