Использование «НЕ СУЩЕСТВУЕТ» считается плохой практикой SQL? - PullRequest
6 голосов
/ 21 июля 2011

За многие годы я слышал, как многие люди говорят:

Операторы «соединения» предпочтительнее, чем «НЕ СУЩЕСТВУЕТ»

Почему?

Ответы [ 3 ]

10 голосов
/ 21 июля 2011

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.

. Возможно, вы захотите прочитать эти статьи:

0 голосов
/ 21 июля 2011

Я думаю, что это особый случай MySQL.MySQL не оптимизирует подзапрос в предложениях IN / not in / any / not exist и фактически выполняет подзапрос для каждой строки, соответствующей внешнему запросу.Из-за этого в MySQL вы должны использовать join.Однако в PostgreSQL вы можете просто использовать подзапрос.

0 голосов
/ 21 июля 2011

Это может быть связано с процессом оптимизации ... NOT EXISTS подразумевает подзапрос, а «оптимизаторы» обычно не отдают должное подзапросам. С другой стороны, с объединениями можно справиться легче ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...