[sql-server] SQL Server IN vs. EXISTS 성능

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

저는 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])



답변

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

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


답변

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

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

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

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

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


답변

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

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


답변

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

(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)


답변

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

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

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

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

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

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

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


답변

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


답변

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

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

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

이걸 고려하세요:

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

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

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

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

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

문안 인사,

MarianoC