[Top-N 쿼리와 조인]

Top-N 쿼리와 조인은 성능과 관련된 주제지만 중요한 내용이다.

​

아래 쿼리는 조인 후 Top-N 처리를 수행한다.

emp 테이블이 14건이므로 조인을 14번 수행하고 2건의 결과를 반환한다.

emp 테이블과 dept 테이블은 조인 차수가 M:1이고, 

아우터 조인으로 조인했기 때문에 emp 테이블을 Top-N 처리한 후 dept 테이블을 조인해도 동일한 결과를 얻을 수 있다.

(emp 테이블이 dept 테이블에 대해 필수 관계를 가지므로 이너 조인으로 조인해도 결과가 동일하다.)

​

SELECT EMPNO, SAL, DEPTNO, DNAME

  FROM (SELECT A.EMPNO, A.SAL, A.DEPTNO, B.DNAME

                  FROM EMP A, DEPT B

                WHERE B.DEPTNO (+) = A.DEPTNO

                ORDER BY A.SAL, A.EMPNO)

WHERE ROWNUM <= 2;

​

아래 쿼리는 위 쿼리와 결과가 동일하다.

인라인 뷰에서 Top-N 처리한 결과 집합으로 DEPT 테이블을 아우터 조인한다.

조인은 2번만 수행된다.

​

SELECT A.EMPNO, A.SAL, A.DEPTNO, B.DNAME

  FROM (SELECT *

                   FROM (SELECT EMPNO, SAL, DEPTNO

                                   FROM EMP

                                  ORDER BY SAL, EMPNO)

            , DEPT B

WHERE B.DEPTNO (+) = A.DEPTNO

ORDER BY A.SAL, A.EMPNO;

​

1개의 열만 조회할 경우 Top-N 처리 후 스칼라 서브 쿼리를 사용할 수 있다.

SELECT A.EMPNO, A.SAL, A.DEPTNO

            , (SELECT X.DNAME FROM DEPT X WHERE X.DEPTNO = A.DEPTNO) AS DNAME

  FROM (SELECT EMPNO, SAL, DEPTNO FROM EMP ORDER BY SAL, EMPNO) A

WHERE ROWNUM <= 2;

​

아래 쿼리는 Top-N 처리 후 조인하는 방식으로 변경할 수 없다.

emp 테이블이 dept 테이블에 대해 필수 관계를 가지더라도 b.loc = 'DALLAS' 조건에 의해 인라인 뷰의 결과 집합이 달라질 수 있기 때문이다.

​

SELECT EMPNO, SAL, DEPTNO, DNAME

  FROM (SELECT A.EMPNO, A.SAL, A.DEPTNO, B.DNAME

                  FROM EMP A, DEPT B

                WHERE B.DEPTNO = A.DEPTNO

                     AND B.LOC = 'DALLAS'

                ORDER BY A.SAL, A.EMPNO)

WHERE ROWNUM <= 2;

​

아래 쿼리에서 결과가 달라진 것을 확인할 수 있다.

SELECT A.EMPNO, A.SAL, A.DEPTNO, B.DNAME

  FROM (SELECT *

                  FROM (SELECT EMPNO, SAL, DEPTNO FROM EMP ORDER BY SAL, EMPNO)

               WHERE ROWNUM <= 2) A

WHERE B.DEPTNO (+) = A.DEPTNO

     AND B.LOC (+) = 'DALLAS'

ORDER BY A.SAL, A.EMPNO;

​

[Top-N 쿼리와 UNION ALL 연산자]

Top-N 쿼리와 UNION ALL 연산자도 성능과 관련된 주제지만 중요한 내용이다.

​

아래 쿼리는 dept 테이블과 emp 테이블을 UNION ALL 연산자로 연결한 결과 집합에 Top-N 처리를 수행한다.

결과 집합을 정렬해야 하므로 소트 부하가 발생할 수 있다.

​

SELECT *

  FROM (SELECT 1 AS TP, DEPTNO AS NO, DNAME AS NAME FROM DEPT 

                UNION ALL

                SELECT 2 AS TP, EMPNO AS NO, ENAME AS NAME FORM EMP

                ORDER BY TP, NO)

WHERE ROWNUM <= 3;

​

아래 쿼리처럼 데이터 집합 별로 Top-N 처리를 수행하면 소트 부하를 경감시킬 수 있다.

UNION ALL 연산자는 순차적으로 수행된다.

아래 쿼리는 emp 테이블을 읽지 않고 결과를 반환한다.

​

SELECT *

  FROM (SELECT *

                  FROM (SELECT 1 AS TP, DEPTNO AS NO, DNAME AS NAME FROM DEPT ORDER BY NO)

                WHERE ROWNUM <= 3

                UNION ALL

                SELECT *

                  FROM (SELECT 2 AS TP, EMPNO AS NO, ENAME AS NAME FROM EMP ORDER BY NO)

                WHERE ROWNUM <= 3)

WHERE ROWNUM <= 3;

 

 

+ Recent posts