IN vs EXISTS에 대한 고찰

지니·2022년 7월 23일
0

SQLP (SQL 전문가)

목록 보기
20/21
post-custom-banner

1. IN

정의

  • 조건에 해당하는 ROW의 컬럼을 비교하여 체크한다.
  • 서브 쿼리의 결괏값을 메인 쿼리에 대입하여 조건 비교 후 결과를 출력한다.


예제

SELECT a.empno
     , a.ename
     , a.deptno
  FROM emp a
 WHERE a.job = 'MANAGER'
   AND a.empno IN (SELECT aa.empno
                 FROM dept_history aa)




2. EXISTS

정의

  • 조건에 해당하는 ROW의 존재 유무 체크 후 더이상 수행하지 않으며 SELECT절을 평가하지 않으므로 일반적으로 IN에 비해 성능이 좋다.
  • 메인 쿼리의 결괏값을 서브 쿼리에 대입하여 조건 비교 후 결과를 출력한다.


예제

SELECT a.empno
     , a.ename
     , a.deptno
  FROM emp a
 WHERE a.job = 'MANAGER'
   AND EXISTS (SELECT 1
                 FROM dept_history aa
                WHERE aa.empno = a.empno)


EXISTS를 사용하면서 저지른 실수

원래 목적

select *
from 월별계좌상태 B
where 상태구분코드 <> '01'
  and 기준연월 = :base_dt
  and exists(select 'X'
             from 계좌원장 A
             where A.계좌번호 = B.계좌번호
               and A.계좌일련번호 = B.계좌일련번호
               AND A.개설일자 like :std_ym || '%');

실수

select *
from 월별계좌상태
where 상태구분코드 <> '01'
  and 기준연월 = :base_dt
  and exists(select 'X'
             from 계좌원장 A
             where A.계좌번호 = 계좌번호
               and A.계좌일련번호 = 계좌일련번호
               AND A.개설일자 like :std_ym || '%');

여기서 서브쿼리에 alias를 달지 않은 컬럼은 서브쿼리 내 테이블의 컬럼으로 인식하는 것 같다. 서브쿼리를 사용할 때는 alias를 달아주는 것이 안전할 것 같다.






3. SQL 튜닝 관점에서 IN과 EXISTS의 차이점

[인덱스 구성]
월말계좌상태_PK : 계좌번호 + 계좌일련번호 + 기준연월
월말계좌상태_X1 : 기준연월 + 상태구분코드

[SQL]

select *
from 월별계좌상태
where 상태구분코드 <> '01'
  and 기준연월 = :base_dt
  and 계좌번호 || 계좌일련번호 in (select 계좌번호 || 계좌일련번호 from 계좌원장 where 개설일자 like :std_ym || '%');

해당 SQL을 월말계좌상태_PK 인덱스로 Range Scan 가능하도록 재작성하는 문제였다.



정답

select *
from 월별계좌상태
where 상태구분코드 <> '01'
  and 기준연월 = :base_dt
  and (계좌번호, 계좌일련번호) in (select A.계좌번호, A.계좌일련번호
                         from 계좌원장 A
                         where A.개설일자 like :std_ym || '%');



오답

select *
from 월별계좌상태 B
where 상태구분코드 <> '01'
  and 기준연월 = :base_dt
  and exists(select 'X'
             from 계좌원장 A
             where A.계좌번호 = B.계좌번호
               and A.계좌일련번호 = B.계좌일련번호
               AND A.개설일자 like :std_ym || '%');
  • 위의 IN과 EXISTS를 실행시켰을 때 결과는 동일하게 나온다. 하지만 EXISTS는 실행계획이 원하는대로 나오지 않는 것을 알 수 있었다.

profile
Coding Duck
post-custom-banner

0개의 댓글