SELECT DISTINCT S.SNAME 
  FROM S, SP 
 WHERE S.S# = SP.S# AND SP.P# = 'P2'

=> 위의 SQL문을 가지고 52개의 다른 SQL문으로 표현이 가능함

<C.J. Date 박사 An Introduction to Database Systems'>


SELECT DISTINCT S.SNAME 
  FROM S
 WHERE S.S# IN (SELECT SP.S# FROM SP WHERE SP.P# = 'P2')';


SELECT DISTINCT S.SNAME 
  FROM S
 WHERE EXISTS (SELECT * FROM SP WHERE SP.P# = S.S# AND SP.P# = 'P2')';


SELECT DISTINCT S.SNAME 
  FROM S, SP 
 WHERE S.S# = SP.S# 
GROUP BY S.SNAME, SP.P#
HAVING SP.P# = 'P2';


SELECT DISTINCT S.SNAME 
  FROM S
 WHERE S.S# ANY (SELECT SP.S# FROM SP WHERE SP.P# = 'P2')';


SELECT DISTINCT S.SNAME 
  FROM S, SP 
 WHERE (SELECT COUNT(*) FROM SP WHERE SP.S# = S.S# AND SP.P# = 'P2') > 0

............기타등등


=> *아래 두 쿼리는 결과는 같지만 수행속도는 다를 수 있다 *

<쿼리1>


SELECT * 
  FROM DEPT D 
 WHERE NOT EXISTS ( SELECT 'X' 
                      FROM EMP 
                     WHERE DEPTNO = D.DEPTNO);

Execution Plan
-------------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=6 Card=1 Bytes=23)
   1    0   MERGE JOIN (ANTI) (Cost=6 Card=1 Bytes=23)
   2    1     TABLE ACCESS (BY INDEX ROWID) OF 'DEPT' (TABLE) (Cost=2 Card=4 Bytes=80)
   3    2       INDEX (FULL SCAN) OF 'PK_DEPT' (INDEX (UNIQUE)) (Cost=1 Card=4)
   4    1     SORT (UNIQUE) (Cost=4 Card=14 Bytes=42)
   5    4       TABLE ACCESS (FULL) OF 'EMP' (TABLE) (Cost=3 Card=14 Bytes=42)


<쿼리2>


SELECT D.*
  FROM DEPT D, EMP E
 WHERE E.DEPTNO(+) = D.DEPTNO
   AND E.ROWID IS NULL;

Execution Plan
--------------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=6 Card=14 Bytes=490)
   1    0   FILTER
   2    1     MERGE JOIN (OUTER) (Cost=6 Card=14 Bytes=490)
   3    2       TABLE ACCESS (BY INDEX ROWID) OF 'DEPT' (TABLE) (Cost=2 Card=4 Bytes=80)
   4    3         INDEX (FULL SCAN) OF 'PK_DEPT' (INDEX (UNIQUE)) (Cost=1 Card=4)
   5    2       SORT (JOIN) (Cost=4 Card=14 Bytes=210)
   6    5         TABLE ACCESS (FULL) OF 'EMP' (TABLE) (Cost=3 Card=14 Bytes=210)


  • 쿼리 변환(Query Transformation)은, 쿼리 옵티마이저가 SQL을 분석해 의미적으로 동일하면서도 더 나은 성능이 기대되는 형태로 재작성 하는 것.
  • 본격적으로 최적화하기에 앞서 사전정지 작업을 하는 것.
  • DBMS 버전이 올라갈수록 쿼리 변환의 종류가 다양해짐은 물론 더 적극적인 시도가 이루어지고 있다.

쿼리 변환의 종류

1. 서브쿼리Unnesting
2. 뷰Merging
3. 조건절Pushing
4. 조건절이행
5. 공통표현식 제거
6. Outer 조인을 Inner 조인으로 변환
7. 실체화 뷰 쿼리로 재작성
8. Star 변환
9. Outer 조인 뷰에 대한 조인 조건 Pushdown
10. OR-expansion

쿼리 변환 작동 방식

  • 휴리스틱(Heuristic) 쿼리 변환 : 결과만 보장된다면 무조건 쿼리 변환을 수행한다.
    일종의 규칙 기반(Rule-based) 최적화 기법이라고 할 수 있으며, 경험적으로 (최소한 동일하거나) 항상 더 나은 성능을 보일 것이라는 옵티마이저 개발팀의 판단이 반영된 것이다.
  • 비용기반(Cost-based) 쿼리 변환 : 변환된 쿼리의 비용이 더 낮을 때만 그것을 사용하고, 그렇지 않을 때는 원본 쿼리 그대로 두고 최적화를 수행한다.