다잇소


[IT/트랜드] 알아두면 편리한 SQL TIP

2018.03.07
김태공_sql팁

 

SQL이 집합의 원리로 구성된거는 모두 아시죠?
AND는 교집합, OR은 합집합 등등…
일반적 차집합은 MINUS JOIN으로 아래같이 간단히 사용하며 A,B 두테이블의 데이타 적은 경우는 빠르게 처리될 것입니다.
단점은 복수개의 다른 컬럼의 ACCESS가 안된다는 거죠.
그리고 프로그램상에서는 가급적 사용하시지 말아야 할 SQL이고요.
주로 DBMS툴에서 데이타를 간단히 보고자 할 경우만 사용해야 합니다.

SELECT 이메일주소 FROM INST1.TSCARTK02 A MINUS SELECT 이메일주소 FROM INST1.TSCARTK03 B;

 

그림1

 

 

 

그러나 데이타 양이 B가 많고 A가 적다면 아래같이 사용하면 유리할것입니다.
이때 B 테이블의 이메일주소 컬럼은 꼭 인덱스가 걸려 있어야 합니다.

SELECT *
FROM INST1.TSCARTK02 A
WHERE NOT EXISTS (SELECT ‘X’ FROM INST1.TSCARTK03 B WHERE B.이메일주소=A.이메일주소);

 

그림2

 

 

현재 실행계획의 오라클은 11G여서 NESTED LOOP JOIN 이 나왔지만… 과거 버젼에서는 주로 FILTER로 표시가 나올것입니다.

만약 A의 데이타가 무척 많고 B가 적거나 A,B 두테이블 전부 데이타가 많다면 아래가 유리합니다.
이때 실행계획을 보고 HASH JOIN이 걸리는지 확인해야 합니다.

SELECT *
FROM INST1.TSCARTK02 A
WHERE A.이메일주소 NOT IN (SELECT B.이메일주소
FROM INST1.TSCARTK03 B);
그림3

 

위의 실행계획을 보면 HASH JOIN 이 아니라 FILTER로 처리했습니다.
FILTER 처리가 항상 나쁜건 아니지만… 대량의 데이타에서는 FILTER처리는 성능이 무척 떨어집니다.
아래같이 약간만 가공한다면 원하는 HASH JOIN이 나타납니다.

SELECT *
FROM INST1.TSCARTK02 A
WHERE A.이메일주소 IS NOT NULL — (??1)
AND A.이메일주소
NOT IN (SELECT /*+ HASH_AJ */ B.이메일주소
FROM INST1.TSCARTK03 B
WHERE B.이메일주소 IS NOT NULL); — (주1)

가끔 (주1) 부분을 코딩 안하면 HASH JOIN으로 수행하지 않는 경우도 있습니다.
항상 실행계획을 보는 습관을 들여야 합니다.

 

 

그림4
단순히 두개의 테이블을 조회한다면 바로 위와같이 처리해도 되겠지만 복잡한 SQL에서는 SUB-QUERY의 통제가 어려울때가 종종 있지요.
그럼 아래같이 INLINE-VIEW를 사용하여 처리하면 유리할 것입니다.

SELECT 이메일주소, 부서명, 이메일주소_CHK
FROM (
SELECT /*+ ORDERED USE_HASH(B) */
A.이메일주소, A.부서명, B.이메일주소 이메일주소_CHK
FROM INST1.TSCARTK02 A, INST1.TSCARTK03 B
WHERE A.이메일주소 = B.이메일주소(+)
)
WHERE 이메일주소_CHK IS NULL;

 

그림5

 

위의 실행계획에서 FILTER 나온 부분은 <WHERE 이메일주소_CHK IS NULL> 조건에 의해 걸려지는 작업이므로 성능에는 지장이 없습니다.
지금까지 알아본 위의 SQL들은 동일한 결과가 나오는 SQL이지만 데이타양이나 추출하고자 하는 성격에 따라 쓰는 방법을 달리해야 성능을 보장 받을수 있습니다.

만약 위의 내용을 모두 이해하고 이미 실전에 적용한 직원이 있다면 댓글을 달아 주시기 바랍니다.
댓글다는 직원에게는 좋은 일이 있을 겁니다. ^^

 
김 석기의 프로필 사진
| Wise리더
관심분야 데이타베이스 Sql튜닝

TAG >
http://daitso.kds.co.kr/70263/ 주소복사
카테고리 레이어 닫기