안녕하세요.
쿼리속도문제 문의 드립니다.
2개의 with문으로 된 데이터이며, A테이블은 3건, B테이블(DBLINK사용)은 0건 조회됩니다.
각각 WITH문은 속도가 빠르며,
JOIN시 속도는 빠른데, OUTER JOIN시 속도가 엄청 느립니다.
쿼리예제)
WITH A_DATA AS (
SELECT * --DATA 3건 조회됨: 쿼리 속도빠름
FROM 업무테이블
WHERE ...
)
, B_DATA AS (
SELECT * --0건조회됨 : : 쿼리 속도빠름
FROM DBLINK테이블
WHERE ...
)
SELECT *
FROM A_DATA A
, B_DATA B
WHERE A.KEY = B.KEY(+) -- > 속도 느림. JOIN시 속도 빠름
뭐가 문제일까요? WITH문은 각각 데이터 조회 후 마지막에 처리하는거 아닌지요?
해결 방법이 있는지 문의 드립니다.
감사합니다.
대용량도 아니고 극소량 3건, 0건인데? 오래 걸린다면?
- 조회량은 작지만, 전체 데이터량은 많을 것 같고
- 조인키에 대한 적절한 인덱스가 없을 것 같습니다.
실행계획을 확인해야 하겠지만
- 이너조인은 조인 방향이 B > A 일 것 같고
- 아우터조인은 조인 방향이 A > B 일 것 같네요
- B 에 적절한 인덱스가 없어서 풀스캔을 하는게 아닐까? 생각됩니다.
만약 조회량이 항상 소량이라면?
- /*+ materialize */ 힌트를 사용해 보세요.
- WITH 구문을 풀어해치지 않고 먼저 수행합니다.
WITH a_data AS ( SELECT /*+ materialize */ * FROM 업무테이블 WHERE ... ) , b_data AS ( SELECT /*+ materialize */ * FROM DBLINK테이블 WHERE ... ) SELECT * FROM a_data a , b_data b WHERE A.KEY = B.KEY(+) ;
작성한 쿼리대로 동작하지 않고 쿼리변환이라는 과정을 통해 쿼리를 최적화 시켜서 실행하게 됩니다.
인라인뷰를 풀어서 메인쿼리와 합치는 뷰머징도 쿼리변환의 하나이구요.
뷰머징이 가능한 경우가 있고 그렇지 않은 경우가 있는데
가능한 경우라면 뷰머징이 동작할 가능성이 높습니다.
WITH 문은 인라인뷰와 동일하게 동작합니다.
만약 WITH 문의집합이 여러번 재사용된다면 인라인뷰와 다르게 동작할 수 있습니다.
materialize 힌트는 WITH 문이 풀어지지 않도록 하는 힌트입니다.
뷰머징이 동작하지 않도록 ROWNUM 을 추가하는 방법도 시도해 보세요.
WITH a_data AS ( SELECT * FROM 업무테이블 WHERE ... ) , b_data AS ( SELECT b.* , ROWNUM rn FROM DBLINK테이블 b WHERE ... ) SELECT * FROM a_data a , b_data b WHERE A.KEY = B.KEY(+) ;