Продуктивність SQL JOIN проти IN?


164

У мене є випадок, коли використання ПРИЄДНАННЯ або ІН дасть мені правильні результати ... Що зазвичай має кращу ефективність і чому? Скільки це залежить від того, на якому сервері баз даних ви працюєте? (FYI я використовую MSSQL)


:) Насправді я шукав іншу статтю, яку використав, коли я досліджував щось подібне деякий час тому, і наткнувся на це помилково
AdaTheDev

Вибачте за можливий дуп ... Не знайшли цього питання під час пошуку
Polaris878

Відповіді:


196

Взагалі кажучи, 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.

Дивіться цю статтю в моєму блозі, щоб отримати детальну інформацію про продуктивність:


Так, має сенс, що вони виконали б те саме, якщо стовпець приєднання буде унікальним (що в моєму випадку)
Polaris878

1
На подібній замітці я повинен використовувати IN (SELECT DISTINCT ...) або просто IN (SELECT ...)?
пн

8
@ orlandu63: INозначає DISTINCT. SQL Serverдосить розумний, щоб його помітити, і створить однакові плани для обох запитів. Не впевнений, однак, як RDBMSповодяться інші.
Quassnoi

>> IN і JOIN - це різні запити, які можуть давати різні результати. Чи можете ви пояснити, чому це призведе до різного результату в цьому випадку, навіть якщо b.col не є унікальним?
Abhijeet

explainextended.com/2009/06/16/in-vs-join-vs-exists На насправді мені допомагає .. Спасибо ..
Аббас Galiyakotwala


6

Це досить важко сказати - для того, щоб дійсно з’ясувати, який з них працює краще, вам потрібно було б насправді проаналізувати терміни виконання.

Як загальне правило, я думаю, якщо у вас є індекси на стовпцях із зовнішнім ключем, і якщо ви використовуєте лише (або в основному) умови ВНУТРІШНЬОГО ПРИЄДНАННЯ, то СПОЛУЧЕННЯ буде трохи швидше.

Але як тільки ви почнете використовувати зовнішній приєднання або якщо вам не вистачає індексів іноземних ключів, IN може стати швидшим.

Марк


Я теж думав про це ... тому що, здається, ПРИЄДНАЙТЕ є більш поширеним випадком і, швидше за все, буде оптимізовано
Polaris878

4

Цікавий запис про логічні відмінності: SQL Server: JOIN vs IN vs EXISTS - логічна різниця

Я майже впевнений, що якщо припустити, що відносини та індекси підтримуються, Join приведе до кращого результату (більше зусиль спрямовано на роботу з цією операцією, ніж з іншими). Якщо ви думаєте про це концептуально, то його різниця між 2 запитами та 1 запитом.

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


4

Ця нитка досить стара, але все ще часто згадується. На мій особистий смак це трохи неповно, тому що є ще один спосіб запитати базу даних за ключовим словом EXISTS, яке я вважаю швидшим швидше.

Тож якщо вас цікавлять лише значення з таблиці a, ви можете використовувати цей запит:

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

Різниця може бути величезною, якщо col не індексується, тому що db не повинен знаходити всі записи в b, які мають однакове значення в col, він повинен знайти лише перший. Якщо немає індексу на b.col і багато записів при скануванні таблиці таблиць може бути наслідком. З IN або JOIN це буде сканування повної таблиці, для EXISTS це буде лише часткове сканування таблиці (поки не буде знайдена перша відповідна запис).

Якщо в b є багато записів, які мають однакове значення col, ви також витратите багато пам’яті для того, щоб прочитати всі ці записи у тимчасовий простір лише для того, щоб знайти свій стан. З наявністю цього, як правило, можна уникнути.

Я часто знаходив EXISTS швидше, ніж IN, навіть якщо є індекс. Це залежить від системи бази даних (оптимізатора), даних і не в останню чергу від типу індексу, який використовується.


3
Для MSSql факт, що існує краще, ніж IN, здається неправдивим. Для отримання додаткової інформації: objasinextended.com/2009/06/16/in-vs-join-vs-exists Тут ви можете прочитати: "Багато хто думає, що EXISTS є більш ефективним, ніж IN, тому що EXISTS повертає лише один ряд. Це не вірно для SQL Server. Як ми бачимо з наведених вище прикладів, EXISTS та IN створюють абсолютно однакові плани. Це тому, що EXISTS є більш гнучким, ніж IN. IN завжди можна переписати як EXISTS (використовуючи просту умову WHERE з еквіортайн ), але не навпаки. "
Micaël Félix

3

Впровадження кожної бази даних, але ви, напевно, можете здогадатися, що всі вони вирішують загальні проблеми більш-менш однаково. Якщо ви використовуєте MSSQL, перегляньте сформований план виконання. Це можна зробити, увімкнувши профайлер і плани виконання. Це дасть вам текстову версію під час виконання команди.

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

Погляньте на план виконання. Наскільки це можливо, уникайте сканувань таблиць, якщо, звичайно, ваша таблиця невелика, в цьому випадку сканування таблиці швидше, ніж використання індексу. Читайте про різні операції з'єднання, які виробляє кожен різний сценарій.


1

Оптимізатор повинен бути досить розумним, щоб дати вам однаковий результат у будь-якому випадку для звичайних запитів. Перевірте план виконання, і вони повинні дати вам те саме. Якщо вони цього не роблять, я, як правило, вважаю ПРИЄДНАЙТЕ швидше. Однак усі системи різні, тому вам слід переконатися в профілі коду в системі.


5
Треба робити? Може бути. Робить це? Ні. Дивіться моє повідомлення.
клетус
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.