SQL Server IN vs. EXISTS 성능


115

다음 중 어느 것이 더 효율적 일지 궁금합니다.

저는 INSQL Server가 결과 집합을 큰 IF진술 로 변환한다고 믿기 때문에 항상 사용에 대해 약간 신중했습니다 . 큰 결과 집합의 경우 성능이 저하 될 수 있습니다. 작은 결과 집합의 경우 둘 중 어느 것이 더 바람직한 지 잘 모르겠습니다. 큰 결과 집합의 EXISTS경우 더 효율적이지 않습니까?

WHERE EXISTS (SELECT * FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)

WHERE bx.BoxID IN (SELECT BoxID FROM Base WHERE [Rank = 2])

8
알아내는 가장 좋은 방법은 그것을 시도하고 몇 가지 측정을하는 것입니다.
Klaus Byskov Pedersen

10
거기에 도착 gazillion에 이에 대한 중복 ......로
marc_s

5
@marc_s-아마도 그럴 것입니다.하지만이 주제에 대한 모든 게시물을 살펴보고 제 경우에 맞는 게시물을 찾는 데 시간이 걸렸을 때 제 질문에 대해 네 가지 답변을 받았습니다.
Randy Minder

7
참고로 가장 성능이 좋은 방법을 원한다면 실제로 결과에 신경 쓰지 않고 행이 실제로 존재 select 1 from Base...하기 where exists때문에 할 수 있습니다.
brad

2
@marc_s 정말 슬프다. 왜냐하면 나는 stackoverflow에 더 이상 쓰레기를 추가하지 않기 위해 게시물을 살펴 보는 데 시간을 할애했기 때문입니다. 나는 내 일을 끝내기 위해 맞춤형 답변이 필요하지 않습니다. 좋은 답변을 몇 대신에 Gazillion 중복을 추가 사고의 종류 그게
IvoC

답변:


140

EXISTS 엔진이 히트를 발견하면 조건이 사실로 판명 되었기 때문에 더 빠를 것입니다.

를 사용하면 IN추가 처리 전에 하위 쿼리에서 모든 결과를 수집합니다.


4
그건 좋은 지적이야. IN 문을 사용하려면 SQL Server가 완전한 결과 집합을 생성 한 다음 큰 IF 문을 만들어야합니다.
Randy Minder

72
이것은 사실 이었지만 현재 버전 (적어도 2008)에서는 옵티마이 저가 훨씬 더 똑똑합니다. 실제로 IN ()을 EXISTS ()처럼 취급합니다.
Aaron Bertrand

11
@Aaron-예, 일반적으로 옵티마이 저는 내부적으로 더 나은 계획을 생성합니다. 그러나 내부 단축키에 의존하는 것은 더 복잡한 시나리오에서 해로울 수 있습니다.
Scott Coates

2
이것은 단지 잘못된 것입니다. 2010 년이었고 여전히 그렇습니다.
Magnus

2
IN 및 EXISTS는 정확히 동일한 쿼리 계획 및 IO를 갖습니다. 성능면에서 다르다고 생각할 이유가 없습니다. 자신을 시간 통계를 확인하고 comprove
Nelssen

40

받아 들여지는 대답은 근시안적이며 질문은 다음과 같이 약간 느슨합니다.

1) 커버링 인덱스가 왼쪽, 오른쪽 또는 양쪽에 있는지 명시 적으로 언급하지 않습니다.

2) 입력 왼쪽 세트와 입력 오른쪽 세트의 크기는 모두 고려하지 않습니다.
(질문은 전체적으로 큰 결과 집합을 언급합니다 .)

나는 옵티마이 저가 (1)과 (2)로 인해 상당한 비용 차이가있을 때 "in"과 "exists"사이를 변환 할 수있을만큼 똑똑하다고 생각합니다. 그렇지 않으면 힌트로 사용될 수 있습니다 (예 : 오른쪽의 검색 가능한 색인).

두 양식 모두 내부적으로 조인 양식으로 변환 할 수 있고, 조인 순서를 반대로하고, 예상 행 수 (왼쪽 및 오른쪽)와 왼쪽, 오른쪽 또는 양쪽의 인덱스 존재를 기반으로 루프, 해시 또는 병합으로 실행할 수 있습니다.


3
이 훌륭한 답변이 더 이상 주목을받지 못한 이유를 모르겠습니다. 양측의 지수 / 구조를 이해하면 동의 할 수 있습니다. 잘했다.
SheldonH 2015

옵티마이 저는 항상IN 및에 대해 동일한 계획을 제공합니다 EXISTS. 시도하고 그들이 같은 계획을하지 않는 경우 가지고 올 (이 적용되지 않습니다 불구 NOT IN하고 NOT EXISTS)
마틴 스미스에게

@MartinSmith 나는 당신이 당신이 말하는 것을 알고 있다고 가정하지만 계획이 항상 동일하다는 증거가 있습니까? 그렇다면 여기에서 10 년 동안의 불일치가 해결 될 것입니다.
MarredCheese 19-06-06

@MarredCheese - 무거운 짐은 다른 주장하는 이것의 하나의 예를 생산하는 사람들이다
마틴 스미스

37

SQL Server 2005 및 2008에서 몇 가지 테스트를 수행했으며 EXISTS와 IN 모두에서 다른 사람들이 언급했듯이 똑같은 실제 실행 계획으로 돌아 왔습니다. Optimizer가 최적입니다. :)

하지만 알아 두어야 할 사항, EXISTS, IN 및 JOIN은 쿼리를 올바르게 표현하지 않으면 때때로 다른 결과를 반환 할 수 있습니다. http://weblogs.sqlteam.com/mladenp/archive/2007/05/18/60210 .aspx


5

여기에는 투표율이 높은 답변을 포함하여 많은 오해의 소지가있는 답변이 있습니다 (하지만 그들의 작전이 해를 끼쳤다 고 생각하지는 않습니다). 짧은 대답은 : 이것들은 동일합니다.

(T-) SQL 언어에는 많은 키워드가 있지만 결국 하드웨어에서 실제로 발생하는 유일한 일은 실행 쿼리 계획에서 볼 수있는 작업입니다.

우리가 호출 할 때 우리가 관계형 (수학 이론) 작업 [NOT] IN과는 [NOT] EXISTS반이 (사용하는 경우 안티 조인이다 NOT). 해당 sql-server 작업 의 이름이 같은 것은 우연이 아닙니다 . 언급 아무런 조작도 없다 IN또는 EXISTS(반) 반 조인 만 - 어디가. 따라서 논리적으로 동등한 INEXISTS선택이 성능에 영향을 미칠 수 있는 방법은 없습니다 . 결과를 얻는 유일한 방법 인 (반) 반 조인 실행 작업이 있기 때문 입니다.

예 :

쿼리 1 ( 계획 )

select * from dt where dt.customer in (select c.code from customer c where c.active=0)

쿼리 2 ( 계획 )

select * from dt where exists (select 1 from customer c where c.code=dt.customer and c.active=0)

테스트 했습니까? 그렇다면 SQL과 결과를 공유 할 수 있습니까?
UnhandledExcepSean

여러 번 테스트했습니다. 다른 테스트 케이스를 만들 수 있지만 테스트 케이스가 최적화 프로그램이 통계가 다른 테이블에서 똑같은 계획을 수행한다는 것을 의미하지는 않습니다. 이로 인해 누군가가 대답이 부분적이라고 생각할 수 있지만 여러 세미 조인 연산자가 존재하지 않는 것은 사실입니다. 어딘가에서 목록을 찾아 링크 할 수 있습니다.
George Menoutis

5

IN을 통해 EXISTS를 사용하겠습니다. 아래 링크를 참조하십시오.

SQL Server : JOIN vs IN vs EXISTS-논리적 차이

IN이 반환 된 결과 측면에서 EXISTS 또는 JOIN과 동일하게 작동한다는 일반적인 오해가 있습니다. 이것은 사실이 아닙니다.

IN : 지정된 값이 하위 쿼리 또는 목록의 값과 일치하면 true를 반환합니다.

Exists : 하위 쿼리에 행이 포함 된 경우 true를 반환합니다.

결합 : 결합 열에서 2 개의 결과 집합을 결합합니다.

블로그 크레딧 : https://stackoverflow.com/users/31345/mladen-prajdic


와, 블로그와 설명에 감사드립니다.
Christian Müller

3

이러한 경우 실행 계획은 일반적으로 동일하지만 옵티마이 저가 인덱스 등의 다른 모든 측면을 어떻게 고려하는지 알기 전까지는 절대 알 수 없습니다.


3

따라서 IN은 EXISTS와 동일하지 않으며 동일한 실행 계획을 생성합니다.

일반적으로 EXISTS는 상관 하위 쿼리에서 사용됩니다. 즉, EXISTS 내부 쿼리를 외부 쿼리와 조인하게됩니다. 그러면 외부 쿼리 조인과 내부 쿼리 조인을 해결 한 다음 둘 다 조인하기 위해 where 절을 일치시켜야하므로 결과를 생성하는 단계가 더 추가됩니다.

일반적으로 IN은 내부 쿼리와 외부 쿼리의 상관 관계없이 사용되며 한 단계 (최상의 시나리오에서)로만 해결할 수 있습니다.

이걸 고려하세요:

  1. IN을 사용하고 내부 쿼리 결과가 수백만 행의 고유 값인 경우 EXISTS 쿼리가 성능이 뛰어나므로 (외부 쿼리와 조인 할 올바른 인덱스가 있음) EXISTS보다 느리게 수행됩니다.

  2. EXISTS를 사용하고 외부 쿼리와의 조인이 복잡한 경우 (수행하는 데 더 많은 시간이 걸리고 적절한 인덱스가 없음) 외부 테이블의 행 수만큼 쿼리 속도가 느려지고 완료하는 데 예상되는 시간이 며칠이 될 수 있습니다. 주어진 하드웨어에 대해 행 수가 허용되거나 데이터 카디널리티가 올바른 경우 (예 : 큰 데이터 세트에서 DISTINCT 값이 적음) IN은 EXISTS보다 빠르게 수행 할 수 있습니다.

  3. 위의 모든 것은 각 테이블에 상당한 양의 행이있을 때 표시됩니다 (공정하게 말하면 캐싱을위한 CPU 처리 및 / 또는 램 임계 값을 초과하는 것을 의미합니다).

따라서 대답은 의존적입니다. IN 또는 EXISTS 내부에 복잡한 쿼리를 작성할 수 있지만 경험적으로는 고유 값이 많은 행이 많은 경우 제한된 고유 값 집합과 EXISTS와 함께 IN을 사용해야합니다.

비결은 스캔 할 행 수를 제한하는 것입니다.

문안 인사,

MarianoC


1

를 최적화하려면 EXISTS매우 문자 그대로 있어야합니다. 무언가가 있어야하지만 상관 하위 쿼리에서 반환 된 데이터는 실제로 필요하지 않습니다. 부울 조건을 평가하고 있습니다.

그래서:

WHERE EXISTS (SELECT TOP 1 1 FROM Base WHERE bx.BoxID = Base.BoxID AND [Rank] = 2)

상관 하위 쿼리가 RBAR이므로 첫 번째 결과 적중은 조건을 true로 만들고 더 이상 처리되지 않습니다.


NULL 처리에주의하지 않으면 누락되거나 왜곡 된 결과를 얻기가 매우 쉽기 때문에 LEFT JOIN + NULL 코딩을 사용할 때는 항상 매우주의해야합니다. EXISTS 또는 CTE (중복 찾기 또는 누락 된 데이터에 대한 합성 삽입)가 동일한 요구 사항을 충족하지 않고 LEFT JOIN + NULL보다 성능이 우수한 상황을 거의 발견하지 못했습니다
Josh Lewis

3
TOP 1은 EXISTS와 함께 사용할 때 완전한 외부 (또는 이벤트 중복) 여야합니다. EXISTS는 항상 일치하는 행을 찾는 즉시 반환합니다.
Karl Kieninger 2015 년

지금까지이 접근 방식으로 성능상의 이점을 보지 못했습니다. 실행 계획의 스크린 샷을 보여주세요
DaFi4 2016 년

-1

내 머리 꼭대기에서 정확하지 않을 수 있습니다.이 경우 두 번째가 더 빠를 것이라고 믿습니다.

  1. 첫 번째에서 상관 하위 쿼리로 인해 각 행에 대해 하위 쿼리가 실행될 수 있습니다.
  2. 두 번째 예에서 하위 쿼리는 상관 관계가 없으므로 한 번만 실행해야합니다.
  3. 두 번째 예에서는 IN일치하는 항목을 찾는 즉시 단락됩니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.