DB Link를 이용한 Query에서 실행계획이 Poor Plan이 되는 문제

Oracle 2010. 12. 15. 17:57

ㅇ 환경적 요소

    Oracle 9iR2이 설치된 DB 서버 한개와 Oracle 10gR2이 설치된 DB 서버 한개가 각각 물리적으로 떨어져서

    구성되어 있는 환경에서 DB Link를 이용하여 양쪽 DB 서버에 존재하는 Table에 접근하여 Data를 읽어가도록

    하기 위해 진행된 상황


ㅇ 증상

    Oracle9i의 A Table와 Oracle10g의 B Table을 조인할 경우, Query 수행 시 App에서 응답없음 상태가

    되는 문제가 발생함.


ㅇ 분석

    Oracle9i의 A Table은 전체 약 300만건의 Data가 존재하고, Join시 사용될 Key값에 대해서 PK가 설정되어

    있는 상태이다.

    Oracle10g의 B Table은 전체 약 400건의 Data가 존재하고, Join시 사용될 Key값에 대해서 PK가 설정되어

    있는 상태이다.

    Query문 예시)    select  a.key, a.value, b.name
                           from   t_b b,
t_a@db_link a
                         where  b.key = a.key

    Test Case 1) Oracle9i에 있는 t_a Table에 대해서 단일 Table Query 수행시 정상적인 실행계획을 가지고

                       결과값이 바로 나타남.

    Test Case 2) Oracle10g에 있는 t_b Table에 대해서 단일 Table Query 수행시 정상적인 실행계획을 가지고

                       결과 값이 바로 나타남

    Test Case 3) 예시문에 제시된 Query문 수행시, 30s가 지나도 결과값이 안나타남.
     
                         ==> 이를 실행 계획을 확인해보니, t_b Table을 Index Full Scan을 하고,

                               t_a Table은 Remote ~~ 라고 표시되어 실행계획이 확인이 안됨.

                               이렇게 두 Table을 읽은 후에, Hash Join으로 처리함.

                               Hash로 실행계획이 풀리는 것을 보니, Oracle 9i의 t_a Table이 DB Link를 통해서

                               읽어오는 과정에서 Full Table Scan으로 풀려지는 것을 의심함.

                        ==> 예시문에 제시된 Query문에 각종 Index Hint를 적용해도 해결이 안됨.

    Test Case 4) Oracle10g쪽 DB Server에서 Oracle9i의 t_a Table을 읽을 때, Where 절을 이용해서
 
                       검색해본 바, 상수값을 입력하여 조회시에는 정상적으로 실행계획이 타는 것처럼

                       결과 값이 바로 나타남. 하지만, 상수값 대신 Oracle10g의 t_b Table의 값을 Where절에서

                       In을 이용해서 적용하면 Test Case 3과 동일한 증상이 나타남.


ㅇ 원인

    A query with an in-subquery where the outer query is remote mapped may produce a poor execution plan
   
     Oracle Support에서 원인을 찾아본 바, 이와 같이 DB Link의 Bug가 발생한다고 함.


ㅇ 해결방법

    Oracle Support에서는 DB Patch를 시행하라고 권고하였으나, 이는 서비스 DB에서 바로 시행할 수 있는

    것이 아니기에, Oracle 9i의 t_a Table을 Oracle9i에 존재하는 임의의 t_c Table과 Index Hint를 이용하여

    무조건 Index를 타도록 Query문을 작성한 후, 이를 View로 생성했다.

    그리고 나서 Oracle10g쪽에서 이 View를 이용해서 Join을 수행하도록 하였더니, 내가 원하는 형태로

    실행 계획이 풀리면서 결과가 정상적으로 나타남.

 
그동안 DB Link를 너무 무심하게 가져다 사용한 것 같다는 생각이 드는 사건이었습니다. 이번 사건을 계기로

DB Link에 대해서 알아본 바, 생각보다 많은 Bug들이 존재한다는 점이 충격적으로 다가오는군요.

내가 잘 알고 있다고, 잘 사용해왔다고 생각했던 기술들이 나의 뒷통수를 후려치는 순간입니다.

"돌다리도 두들겨 건너라."라는 옛 속담처럼, 확인에 확인을 하는 습관만이 삽질과 야근으로부터

해방시켜줄 수 있는 방안이 아닐까 합니다.

:     

TISTORY에 Login하려면 여기를 누르세요.