Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

IN срещу JOIN с големи набори от редове

Актуализация:

Тази статия в моя блог обобщава както моя отговор, така и моите коментари към други отговори и показва действителни планове за изпълнение:

SELECT  *
FROM    a
WHERE   a.c IN (SELECT d FROM b)

SELECT  a.*
FROM    a
JOIN    b
ON      a.c = b.d

Тези заявки не са еквивалентни. Те могат да дадат различни резултати, ако вашата таблица b не е запазен ключ (т.е. стойностите на b.d не са уникални).

Еквивалентът на първата заявка е следният:

SELECT  a.*
FROM    a
JOIN    (
        SELECT  DISTINCT d
        FROM    b
        ) bo
ON      a.c = bo.d

Ако b.d е UNIQUE и маркиран като такъв (с UNIQUE INDEX или UNIQUE CONSTRAINT ), тогава тези заявки са идентични и най-вероятно ще използват идентични планове, тъй като SQL Server е достатъчно умен, за да вземе това предвид.

SQL Server може да използва един от следните методи за изпълнение на тази заявка:

  • Ако има индекс на a.c , d е UNIQUE и b е относително малък в сравнение с a , тогава условието се разпространява в подзаявката и обикновения INNER JOIN се използва (с b водещ)

  • Ако има индекс на b.d и d не е UNIQUE , тогава условието също се разпространява и LEFT SEMI JOIN се използва. Може да се използва и за горното състояние.

  • Ако има индекс и на двата b.d и a.c и те са големи, тогава MERGE SEMI JOIN се използва

  • Ако няма индекс на която и да е таблица, тогава се изгражда хеш таблица върху b и HASH SEMI JOIN се използва.

Нито от тези методи преоценява цялата подзаявка всеки път.

Вижте този запис в моя блог за повече подробности как работи това:

Има връзки за всички RDBMS е от голямата четворка.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Преименуване на колона без прекъсване на скриптовете и съхранените процедури

  2. Поправка:„BACKUP LOG не може да се извърши, защото няма текущо архивиране на базата данни.“ в SQL Server/SQL Edge

  3. Възстановяване на паралелно архивиране на SQL Server -1

  4. Как да върна динамични колони от групирани стойности в SQL Server (съхранена процедура)

  5. Какъв низ да използвам за свързване към SQL Server?