우리 회사 데이터베이스를 티베로로 변경하기
에피소드 0 0 99,999+

by 티베로 티베로전환 [2018.10.01]


모든 장애를 분석할 때 가장 기본이 되는 것은 장애시점 대비 가장 최근에 변경이 가해진 것부터 확인을 해야 한다는 점이다. 이유는 해당 변경 작업 시 예상치 못했 던 영향으로 장애가 발생할 가능성이 매우 높기 때문이며, 경험상 이는 굉장히 현 명한 접근방법이다.

게다가 데이터베이스 전환은 단순한 설정 작업과는 달리 모든 업무에 영향을 줄 수 있으므로 티베로 전환을 완료하고 당분간은 어떠한 문제가 발생했을 때 관련된 모 든 담당자가 티베로의 문제는 아닌지 먼저 의심하게 됨은 데이터베이스 관리자나 티베로 엔지니어가 감수해야할 몫일 것이다.

데이터베이스 관리자가 해야 할 일은 그러한 리포트를 받았을 때 친절하고 전문적으로 티베로 문제가 아님을 증명함으 로써 관련된 담당자들에게 데이터베이스의 신뢰도를 스스로 깨닫게 해주는 것이라 고 생각한다. 다음에 소개하는 두 가지 에피소드는 담당자가 데이터베이스 문제라 고 강하게 확신하였지만 티베로는 아무런 문제가 없음을 증명한 사건이다.

1) RANK VS ROW_NUMBER

티베로 오픈 후 데이터에 문제가 생겼다는 연락을 받았다. 소속 회사가 진행한 프 로젝트 방법론은 SQL의 성능과 실패에 대한 호환성을 외산 DBMS 수준으로 만드 는 것이 목표였고 정확한 데이터가 구축되고, 추출되는 부분은 많은 검증을 하지 않고 당연히 될 것이라 생각하며 티베로 엔진을 신뢰하였다.

그러기에 사전에 대비 하지 못한 부분인 ‘데이터에 문제가 생겼다는 연락’은 가장 두려운 일 중에 하나였 기에 상당히 긴장했었으나, 다행히도 담당자가 RANK 함수와 ROW_NUMBER 함수의 정확한 사용법을 착각해서 발생한 에피소드에 불과했다. 어떤 문제였는지 먼 저 정의를 살펴보자.

  • RANK, ROW_NUMBER 함수의 정의 (출처 : 티베로 SQL 가이드 , http://technet.tmaxsoft.com)
  • 가. row_number : 그룹 내의 로우를 정렬한 다음 각 로우에 유일한 번호를 부여하여 값 비교
  • 나. rank : 그룹 내의 로우를 정렬한 다음 그룹 내의 각 로우에 대한 순위를 돌려주는 함수

위 정의만 보아도 어떠한 문제인지 예상했을 것이다. ROW_NUBMER 함수는 PARTITION BY로 구분된 그룹 안에 중복이 있더라도 유일한 번호를 부여하는 것 에 비해 RANK의 경우 순위를 부여하기 때문에 동일 값은 동일한 순위를 부여하는 것이 정상이다.

따라서 유일한 값을 기대하며 RANK 함수를 사용한 것이 잘못된 점이고 티베로에는 아무런 문제가 없음을 확인, 필요 시 ROW_NUMBER 함수를 사용할 것을 친절히 안내하였다.

  • [참고 5-10] RANK, ROW_NUMBER 함수 수행
  • SELECT A,B, RANK() OVER(PARTITION BY A ORDER BY A,B) AS RANK_COL
    FROM
    (
    SELECT '1' A, '100' B FROM DUAL UNION ALL
    SELECT '1' A, '100' B FROM DUAL UNION ALL
    SELECT '1' A, '150' B FROM DUAL UNION ALL
    SELECT '1' A, '200' B FROM DUAL UNION ALL
    SELECT '2' A, '100' B FROM DUAL UNION ALL
    SELECT '2' A, '150' B FROM DUAL UNION ALL
    SELECT '2' A, '200' B FROM DUAL
    );
    
    A B RANK_COL
    - ---- ------------
    1 100 1
    1 100 1 <-- 중복 발생
    1 150 3
    1 200 4
    2 100 1
    2 150 2
    2 200 3
    
    
    SELECT A,B, ROW_NUMBER() OVER(PARTITION BY A ORDER BY A,B) AS RANK_COL
    FROM
    (
    SELECT '1' A, '100' B FROM DUAL UNION ALL
    SELECT '1' A, '100' B FROM DUAL UNION ALL
    SELECT '1' A, '150' B FROM DUAL UNION ALL
    SELECT '1' A, '200' B FROM DUAL UNION ALL
    SELECT '2' A, '100' B FROM DUAL UNION ALL
    SELECT '2' A, '150' B FROM DUAL UNION ALL
    SELECT '2' A, '200' B FROM DUAL
    );
    
    A B RANK_COL
    - --- ---------
    1 100 1
    1 100 2
    1 150 3
    1 200 4
    2 100 1
    2 150 2
    2 200 3
    
    

2) 힌트(HINT)의 오타

/*+ INDEX_DESC(MAXTEST MAXTEST_IDX01) */와 같이 옵티마이저에 어떠 한 인덱스를 사용할지 직접 지시하는 힌트를 사용하는 SQL을 종종 확인할 수 있 다.

그런데 이때 힌트에 쓰여진 테이블 혹은 인덱스 이름에 오타가 발생하여 실제 오브젝트 이름과 상이하게 되면 위 힌트는 당연히 사용되지 않을 것이다.

사실 오 타가 발생한 것은 SQL 문장과 힌트를 비교하면 되므로 쉽게 발견할 수 있는 문제 인데 소속 회사에서 발생한 오타는 쉽게 발견하지 못해 한참 동안을 티베로가 힌트 를 제대로 사용하지 못해 발생하는 문제로 착각했던 사례가 있어 소개한다. 다음의 내용을 살펴보자.

  • 1. 소속 회사에서 사용한 SQL
  • /*+ INDEX_DESC(MAXTEST MAXTEST_IDX01) */ PROCESS_DT FROM TIBEROTEST.MAXTEST WHERE ROWNUM < 2;
  • 2. 소속 회사의 인덱스 명명 규칙
  • 테이블_IDX 순번(예 : MAXTEST 테이블의 첫 번째 인덱스는 MAXTEST_IDX01)

인덱스 명명규칙을 고려했을 때 힌트는 전혀 문제가 없는 것으로 보인다(실제로 문 제가 없다고 생각했었다). MAXTEST라는 테이블 이름도 오타가 없고 MAXTEST_ IDX01의 이름도 정확하다. 뭐가 문제였을까?

문제는 MAXTEST가 실제 테이블명 과 다른 동의어(SYNONYM)라는 것이었다. 소속 회사는 테이블 이름과 다른 동의 어를 사용하는 경우가 거의 없으므로 MAXTEST가 동의어라고는 생각지도 못하였 다.

실제로 MAXREAL이 테이블 이름이고 인덱스도 그에 해당하는 MAXREAL_ IDX01이었다. 따라서 오타 없는 제대로 된 힌트는 아래와 같다.

/*+ INDEX_DESC(MAXTEST MAXREAL_IDX01) */ 
PROCESS_DT FROM TIBEROTEST.MAXTEST WHERE ROWNUM < 2;

위 문제는 힌트를 올바르게 적용해서 처리하였다. 그리고 티베로 프로젝트가 종료 된 지금 시점에서 생각해보니 프로젝트 진행 중에도 발견된 이슈가 실제 티베로 문 제인지 사용방법의 문제인지를 밝히는 데 꽤 많은 시간이 투여되었고, 때로는 무조 건 데이터베이스 문제로 생각하는 관련 담당자의 태도에 서운하기도 했었던 것 같 다.

그러나 서두에서 밝힌 것처럼 이러한 과정 역시 전환 작업 과정 중에 하나이며 넘어야 할 산이고 감당해야할 몫이라고 생각한다.

  • - 해당 강좌는 도서 " [우리 회사 데이터베이스를 티베로로 변경하기]"의 내용을 옮겼습니다.
  • - 해당 도서는 기간계 DBMS(DATABASE MANAGEMENT SYSTEM)를 티베로로 전환하는 실제 프로젝트를 수행한 실무자가 DBMS 전환 과정과 실제 적용 사례, 문제 해결 과정 등을 자세하게 설명하고 있습니다.

- 강좌 URL : http://www.gurubee.net/lecture/4147

- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^

- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입