In MySQL
, Oracle
, SQL Server
и PostgreSQL
, NOT EXISTS
имеют одинаковую или даже более высокую эффективность, чем LEFT JOIN / IS NULL
.
Хотя может показаться, что "внутренний запрос должен быть выполнен для каждой записи из внешнего запроса "(что плохо для NOT EXISTS
и даже хуже для NOT IN
, поскольку последний запрос даже не коррелирован), он может быть оптимизирован так же, как и вседругие запросы оптимизируются с использованием соответствующих методов anti-join
.
В SQL Server
, на самом деле, LEFT JOIN / IS NULL
может быть менее эффективным, чем NOT EXISTS / NOT IN
в случае столбца с неиндексированной или низкой мощностью во внутренней таблице.
Часто говорят, что MySQL
"особенно плохо подходит для обработки подзапросов".
Это связано с тем фактом, что MySQL
не способен использовать любые методы соединения, кроме вложенных циклов, которыестрого ограничивает возможности оптимизации.
Единственный случай, когда запрос извлечет выгоду от переписывания подзапроса в качестве объединения, будет следующим:
SELECT *
FROM big_table
WHERE big_table_column IN
(
SELECT small_table_column
FROM small_table
)
small_table
не будет запрошен полностью для каждой записив 1029 *: хотя это, кажется, не коррелируется, оно будет неявно коррелировано оптимизатором запросов и фактически переписано в EXISTS
(используя index_subquery
для поиска первого, если это необходимо, если индексирован small_table_column
)
Но big_table
всегда будет ведущим, что делает запрос завершенным при big * LOG(small)
, а не small * LOG(big)
чтениях.
Это можно переписать как
SELECT DISTINCT bt.*
FROM small_table st
JOIN big_table bt
ON bt.big_table_column = st.small_table_column
Однако, это не улучшится NOT IN
(в отличие от IN
).В MySQL
, NOT EXISTS
и LEFT JOIN / IS NULL
почти одинаковы, поскольку при вложенных циклах левая таблица всегда должна быть ведущей в LEFT JOIN
.
. Возможно, вы захотите прочитать эти статьи: