http://blog.naver.com/ebank13?Redirect=Log&logNo=400183846853.Exists
SQL문에서 Exists를 사용하는 것은
어떤 조건을 만족하는 집합의 존재 여부를 확인할 경우에 사용합니다. Exits는 주어진 조건을 만족하는 첫 번째 열을 만나면 트랜잭션을 멈추게 됩니다. 즉, 조건을 만족하면 처리를 멈추고 다음의 처리를 수행합니다. 그러나 Exists를 사용하지 않은 경우는 일반적으로 만족하는 조건을 모두 Search한 이후에 다음 처리를 수행함으로서 Access하는 횟수가 많아지게 됩니다.
<왼쪽><오른쪽>(Exist를 쓰는 게 훨 빠르다는 그림)
왼쪽의 SQL문은 EXISTS를 사용하지 않고 전체 COUNT를 구하여 COUNT가 0보다 큰 경우에 IF 조건문을 수행하는 프로그램입니다. 전체 COUNT를 구하기 위해서 해당되는 인덱스를 ACCESS한 후 테이블도 ACCESS했습니다. 그와 반면에 EXISTS를 사용하는 오른쪽 SQL문은 인덱스를 ACCESS한 후 테이블 ACCESS시에 한 건이 해당 될 경우에 인덱스 및 테이블 ACCESS를 멈추고 IF 조건문을 수행하고 있습니다.
즉 EXISTS를 사용하는 오른쪽 SQL문은 인덱스와 테이블을 조건문에서 해당되는 범위의 일부만 ACCESS하는 반면에 EXISTS를 사용하지 않는 왼쪽 SQL은 조건문에서 해당되는 범위 전체를 ACCESS하는 큰 차이점이 있습니다. 인덱스나 테이블의 ACCESS하는 횟수가 많으면 많을 수록 EXISTS를 사용하는 않는 왼쪽의 PROGRAM과 EXISTS를 사용하는 오른쪽의 프로그램의 수행속도는 크게 차이가 납니다. 당연히, 오른쪽이 빠르겠지요?
다음의 프로그램을
보시면 굳이 전체 건수를 알지 않아도 되는 것을 전체 건수를 알고 프로세스를 진행시키고 있습니다. 문제점 및 해결책에 대해서 학습하시도록 하겠습니다.
예)
SELECT COUNT(*) INTO :CNT
FROM DPCRII A
WHERE DP_ACNO = '123456'
AND SEQ > 100
.........
IF CNT > 0 ...
........
위의 프로그램은 SQL문에서 건수(CNT)를 구하고 아래 IF조건절에서 건수(CNT)가 0 이상이면 문장을 수행하고 등등을 수행하는 것입니다.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 INDEX (RANGE SCAN) OF 'DPCRII_PK' (UNIQUE)
위 실행계획은 INDEX DPCRII_PK를 먼저 ACCESS한 후 해당되는 로우들을 모두 ACCESS한 이후에 건수를 구하기 위하여 SORT(AGGREGATE)를 했습니다. 위 프로그램에서는 CNT를 구하여 그 값이 1이상이면 동일한 프로세스를 수행하고 있습니다. 그러면 여기서 CNT의 값이 1이상이면 SQL의 트랜잭션을 멈추고 다른 문장을 수행해도 문제는 없습니다. 따라서 이런 경우에 Exists문을 사용하여 SQL문에서 최소한의 수행시간이 걸리도록 SQL문을 수정하였습니다.
예) --> 이렇게 수정
SELECT 1 INTO :CNT FROM DUAL
WHERE EXISTS
( SELECT 'X'
FROM DPCRII A
WHERE DP_ACNO = '12345'
AND SEQ > 100 )
.........
IF CNT > 0 ...
........
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 FILTER
2 1 TABLE ACCESS (FULL) OF 'DUAL'
3 1 INDEX (RANGE SCAN) OF 'DPCRII_PK' (UNIQUE)
Trackback | http://seamist0.tistory.com/trackback/405