SQL JOIN против производительности?

164

У меня есть случай, когда использование JOIN или IN даст мне правильные результаты ... Какой тип обычно имеет лучшую производительность и почему? Насколько это зависит от того, на каком сервере базы данных вы работаете? (К сведению, я использую MSSQL)

Polaris878
источник
:) Я на самом деле искал другую статью, которую использовал, когда недавно исследовал нечто подобное, и наткнулся на
нее
Извините за возможный обман ... не нашел этот вопрос, когда я искал
Polaris878

Ответы:

197

Вообще говоря, INи JOINэто разные запросы, которые могут давать разные результаты.

SELECT  a.*
FROM    a
JOIN    b
ON      a.col = b.col

это не то же самое, что

SELECT  a.*
FROM    a
WHERE   col IN
        (
        SELECT  col
        FROM    b
        )

, если b.colне уникален.

Однако это синоним первого запроса:

SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT col
        FROM    b
        )
ON      b.col = a.col

Если объединяющий столбец UNIQUEпомечен и помечен как таковой, оба этих запроса дают один и тот же план в SQL Server.

Если это не так, то INбыстрее, чем JOINна DISTINCT.

Смотрите эту статью в моем блоге для деталей производительности:

Quassnoi
источник
Да, имеет смысл, что они будут выполнять то же самое, если соединительный столбец уникален (что в моем случае)
Polaris878
1
На аналогичной ноте, я должен использовать IN (SELECT DISTINCT ...) или просто IN (SELECT ...)?
мычание
8
@ orlandu63: INподразумевается DISTINCT. SQL Serverдостаточно умен, чтобы заметить это, и будет генерировать одинаковые планы для обоих запросов. Не уверен, однако, как RDBMSбудут вести себя другие.
Quassnoi
>> IN и JOIN - это разные запросы, которые могут давать разные результаты. Не могли бы вы объяснить, почему это привело бы к другому результату в этом случае, даже если b.col не уникален?
Абхиджит
1
explainextended.com/2009/06/16/in-vs-join-vs-exists На самом деле мне помогает .. Спасибо ..
Аббас Galiyakotwala
6

Это довольно сложно сказать - чтобы действительно выяснить, какой из них работает лучше, вам нужно было бы профилировать время выполнения.

Как общее практическое правило, я думаю, что если у вас есть индексы в столбцах внешнего ключа и если вы используете только (или в основном) условия INNER JOIN, то JOIN будет немного быстрее.

Но как только вы начнете использовать OUTER JOIN, или если вам не хватает индексов внешнего ключа, IN может быть быстрее.

Марк

marc_s
источник
Я тоже думал об этом ... потому что кажется, что JOIN - более распространенный случай, и он, скорее всего, будет оптимизирован
Polaris878
4

Интересная статья о логических различиях: SQL Server: JOIN против IN против EXISTS - логическое различие

Я вполне уверен, что при условии сохранения отношений и индексов соединение будет работать лучше в целом (больше усилий уходит на работу с этой операцией, чем с другими). Если вы думаете об этом концептуально, то разница между 2 запросами и 1 запросом.

Вам нужно подключить его к Query Analyzer, попробовать и увидеть разницу. Также посмотрите на План выполнения запросов и постарайтесь свести к минимуму количество шагов.

AdamSane
источник
4

Эта тема довольно старая, но часто упоминается. На мой личный вкус это немного неполно, потому что есть другой способ запросить базу данных с ключевым словом EXISTS, которое я нашел быстрее, чем нет.

Поэтому, если вас интересуют только значения из таблицы a, вы можете использовать этот запрос:

SELECT  a.*
FROM    a
WHERE   EXISTS (
    SELECT  *
    FROM    b
    WHERE   b.col = a.col
    )

Разница может быть огромной, если col не проиндексирован, потому что БД не нужно находить все записи в b, которые имеют одинаковое значение в col, он должен найти только самую первую. Если на b.col нет индекса, а при просмотре таблицы ba может быть много записей, это может быть следствием. Для IN или JOIN это будет полное сканирование таблицы, для EXISTS это будет только частичное сканирование таблицы (до тех пор, пока не будет найдена первая соответствующая запись).

Если в b много записей с одинаковым значением col, вы также потратите много памяти на чтение всех этих записей во временное пространство, просто чтобы убедиться, что ваше условие удовлетворено. С существующим этого обычно можно избежать.

Я часто находил EXISTS быстрее, чем IN, даже если есть индекс. Это зависит от системы баз данных (оптимизатора), данных и, что не менее важно, от типа используемого индекса.

S.Roeper
источник
3
На MSSql тот факт, что существует лучше, чем IN, кажется неправдой. Для получения более подробной информации: объяснитесь сxtended.com/2009/06/16/in-vs-join-vs-exists Здесь вы можете прочитать, что: «Многие думают, что EXISTS более эффективен, чем IN, потому что EXISTS возвращает только одну строку. не верно для SQL Server. Как видно из приведенных выше примеров, EXISTS и IN создают точно такие же планы. Это связано с тем, что EXISTS более гибок, чем IN. IN всегда можно переписать как EXISTS (используя простое условие WHERE с эквивалентным равенством ) но не наоборот ".
Микаэль Феликс
3

Реализация каждой базы данных, но вы, вероятно, можете догадаться, что все они решают общие проблемы более или менее одинаково. Если вы используете MSSQL, взгляните на сгенерированный план выполнения. Вы можете сделать это, включив профилировщик и планы выполнения. Это даст вам текстовую версию при запуске команды.

Я не уверен, какую версию MSSQL вы используете, но вы можете получить графическую версию в SQL Server 2000 в анализаторе запросов. Я уверен, что эта функция скрывается где-то в SQL Server Studio Manager в более поздних версиях.

Посмотрите на план выставки. По возможности избегайте сканирования таблиц, если, конечно, ваша таблица не мала, и в этом случае сканирование таблицы выполняется быстрее, чем при использовании индекса. Ознакомьтесь с различными операциями соединения, которые создает каждый другой сценарий.

Uridium
источник
1

Оптимизатор должен быть достаточно умен, чтобы дать одинаковый результат в любом случае для обычных запросов. Проверьте план выполнения, и они должны дать вам то же самое. Если они этого не делают, я обычно считаю, что JOIN быстрее. Тем не менее, все системы разные, поэтому вы должны быть уверены, что профиль вашего кода должен быть профилирован.

Джоэл Коухорн
источник
5
Стоит сделать? Может быть. Является ли? Нет. Смотрите мой пост.
Клет