5.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN
5.2.6 Как MySQL оптимизирует LEFT JOIN и RIGHT JOIN
Выражение "A LEFT JOIN B" в MySQL реализовано следующим образом:
- Таблица B устанавливается как зависимая от таблицы A и от всех таблиц, от которых зависит A.
- Таблица A устанавливается как зависимая ото всех таблиц (кроме B), которые используются в условии LEFT JOIN.
- Все условия LEFT JOIN перемещаются в предложение WHERE.
- Выполняются все стандартные способы оптимизации соединения, за исключением того, что таблица всегда читается после всех таблиц, от которых она зависит. Если имеется циклическая зависимость, MySQL выдаст ошибку.
- Выполняются все стандартные способы оптимизации WHERE.
- Если в таблице A имеется строка, соответствующая выражению WHERE, но в таблице B ни одна строка не удовлетворяет условию LEFT JOIN, генерируется дополнительная строка B, в которой все значения столбцов устанавливаются в NULL.
- Если LEFT JOIN используется для поиска тех строк, которые отсутствуют в некоторой таблице, и в предложении WHERE выполняется следующая проверка: column_name IS NULL, где column_name - столбец, который объявлен как NOT NULL, MySQL пререстанет искать строки (для отдельной комбинации ключа) после того, как найдет строку, соответствующую условию LEFT JOIN.
RIGHT JOIN реализован аналогично LEFT JOIN.
При указании жесткого порядка чтения таблиц в LEFT JOIN и STRAIGHT JOIN оптимизатор связей (который определяет, в каком порядке таблицы должны быть связаны) будет выполнять работу намного быстрее, так как ему потребуется проверять меньшее количество перестановок таблиц.
Обратите внимание: отсюда следует, что если выполняется запрос типа
SELECT * FROM a,b LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key) WHERE b.key=d.key
MySQL будет делать полный просмотр таблицы b, поскольку LEFT JOIN заставит его читать эту таблицу перед d.
В этом случае, чтобы предотвратить полный просмотр таблицы b, нужно изменить запрос таким образом:
SELECT * FROM b,a LEFT JOIN c ON (c.key=a.key) LEFT JOIN d (d.key=a.key) WHERE b.key=d.key