기본 콘텐츠로 건너뛰기

사례 : 예외 로직 개선

컬럼의 부분값 검색을 위해 SUBSTR 함수 같은 예외적인 로직을 사용함으로써 인덱스를 사용하지 못하고, 최적 실행계획이 수립되지 않는 경우, 그런 예외 로직을 개선한다.

개선 전



  1. (문제 상황) 관리내역 데이터를 과다하게 액세스함
  2. (문제 원인) 암호화고객실명번호, 접촉전화번호 컬럼 조건절이 액세스 범위를 크게 줄일 수 있으나, 그 컬럼이 선두인  인덱스가 없고, 만약 있더라도 조건절의 ‘예외처리’로직으로 인해 그런 인덱스를 사용할 수 없는 상태임
  • 참고로, 예외로직은 암호화고객실명번호 값이 NULL이면 암호화고객실명번호 컬럼 대신 고객실명번호 컬럼을 사용하라는 로직이며, NVL, DEDODE, OR 구문을 사용하면 적절한 인덱스가 있더라도 옵티마이저가 최적 실행계획을 수립하기 어려움

개선 방안




  1. (개선 방안) 암호화고객실명번호, 접촉전화번호 각각 선두인 인덱스 2개를 생성함
  2. (개선 방안) 인덱스 사용을 어렵게 하는 예외로직을 수정함
  • 테이블 데이터를 조사해 보면 암호화고객실명번호 값이 NULL이면서 고객실명번호 값이 NULL이 아닌 것은 전체 15백만 건 중 1600여건(약 0.1%)으로 확인되며, 게다가 그 값은 암호화 불가한 비정상적인 값이고 조회할 가능성이 없는 값이어서 결국 예외로직이 무의미한 것으로 판단함 (따라서, 데이터 정제 대상임)

개선 후



  1. (개선 결과) 암호화고객실명번호 컬럼 조건절 및 접촉전화번호 컬럼 조건절이 인덱스 access 조건이 되면서 액세스량이  개선 전에 비해 현저히 감소함

댓글

이 블로그의 인기 게시물

사례 : 실행계획 분리 - OR EXPANSION

복잡한 선택적 조건절을 사용하는 경우, 옵티마이저가 최적 실행계획을 수립하기 어려운데, 쿼리 수정 또는 USE_CONCAT 힌트 사용을 통해 OR EXPANSION을 유도하거나, UNION ALL 구문으로 입력 케이스별로 실행계획을 강제적으로 분리시키는 방법을 사용하여 성능을 최적화한다. 개선 전 (문제 상황) PK 인덱스가 참조번호+거래일련번호로 구성되었음에도 불구하고, 거래일련번호 컬럼 조건절이 인덱스 access  조건이 되지 못하고 인덱스 filter 조건이 됨 (문제 원인) 조건절 로직에 따라 :b1값이 입력되는 경우와 입력되지 않는 경우의 실행계획이 분리될 필요가 있었는데(OR  EXPANSION 실행계획이 수립될 수도 있었는데), 현재의 조건절은 그렇게 작성되지 않았음 개선 후 (개선 방안) OR EXPANSION 실행계획이 자연스럽게 만들어질 수 있도록 조건절을 수정함 (개선 결과) :b1 변수값 입력 여부에 따라 실행계획이 분리되었고(CONCATENATION 및 FILTER 오퍼레이션  등장), 개선 전 보다 액세스량이 현저히 감소함

사례 : 실행계획 분리 - UNION ALL

복잡한 선택적 조건절을 사용하는 경우, 옵티마이저가 최적 실행계획을 수립하기 어려운데, 쿼리 수정 또는 USE_CONCAT 힌트 사용을 통해 OR EXPANSION을 유도하거나, UNION ALL 구문으로 입력 케이스별로 실행계획을 강제적으로 분리시키는 방법을 사용하여 성능을 최적화 한다. 개선 전 - 트레이스 결과 (문제 상황) 외환기본_IX08 인덱스 액세스에 대부분의 시간이 소요됨 IX08 인덱스가 거래일자와 과목코드 순으로 구성되어 있어서, 거래일자 범위 조건은 인덱스 access 조건이 되었지만,  과목코드 조건을 인덱스 filter 조건이 됨 (참고로, 과목코드 값이 ‘EX’인 것은 전체 로우의 약 5%임) 개선 전 - SQL문 (문제 원인) 고객번호 및 관리점번호 입력값이 필수가 아니어서, 해당 값 입력 여부에 따라 최적 실행계획이 달라질 수  있는데, 앞의 실행계획을 보면, 고객번호(:B3) 입력 여부 따라 실행계획이 분리되었음 (CONCATENATION/FILTER 오퍼레이션  등장) INDEX 힌트를 사용하여 항상 IX08 인덱스가 사용되도록 했는데, 이 INDEX 힌트를 제거하더라도 최적 실행계획이 수립되지  않았음 개선 방안 (개선 방안) 고객번호와 관리점번호 입력 여부에 따른 3가지  경우 각각을 구분하여 처리할 수 있도록 UNION ALL 사용 이때, 배타적인 3개 집합은 반드시 상호 배제되고 전체를  포괄해야 함 (MECE, Mutually Exclusive, Collectively Exhaustive) 개선 후 (개선 결과) 3가지 경우 각각에 최적인 실행계획이 수립됨(각각 IX01, IX04, IX08 인덱스를 사용) (개선 결과) 본 사례는 고객번호가 입력된 경우로서 IX01 인덱스가 사용되었고, 개선 전에 비해 액세스량/소요시간이  현저히 감소함

사례 : 정렬재구성으로 분산도 개선

시계열성으로 쌓여진 (대용량) 거래 내역을 특정 고객번호로 조회하면, 액세스할 블록이 거의 로우당 1개인 경우가 일반적인데, 이때 고객번호별로 데이터를 모아두는 정렬재구성을 하면, 액세스해야 할 블록이 크게 감소한다. 참고로, 온라인 업무나 업무 배치 처리 과정에서 자연스럽게 데이터가 흩어진게 아니고, 차세대/고도화 사업 데이터이행 과정에서 데이터가 크게 흩어지는 경우도 빈번하다. 개선 전 (문제 상황) 평이한 실행계획이나 넓은 데이터 범위를 액세스하면서 10초 가량 소요됨(특히 계좌가 많은 기업고객인 경우) (문제 원인) 16천 여건의 결과 모두를 리턴해야 하므로 절대적으로 많은 시간이 소요될 수 밖에 없고, 특히 클러스터링  팩터가 좋지 못해 읽은 로우수에 비해 읽은 블록도 많은 편임 - 인덱스 스캔 결과가 16899건 인데, 테이블 (12182-281)  블록을 읽었음 참고로, 조건절 정보(Predicate Information)를 볼때, IX04 인덱스는 고객번호+...+여신활동구분코드로 구성되어 있음을 추정할 수 있음 문제 원인 분석 기업고객의 계좌가 한꺼번에 개설되지 않고 시차를 두고 개설되었다면 해당 고객의 계좌 정보는 각기 다른 데이터  블록에 저장됨 참고로 하나의 데이터 블록은 (보통) 8K byte 크기이며, 대개 100건 이상의 로우가 저장될 수 있음 참고로, 차세대 또는 통합 프로젝트의 데이터이행 과정을 통해서도 데이터가 크게 흩어질 수 있음 계좌 데이터가 저장된 모든 데이터 블록을 액세스 해야 하는데, 여신계약기본과 같은 대형 테이블의 데이터 블록이 DB 캐시에 있을 확률은 (보통) 10% 내외이므로 거의 계좌 건수 만큼 물리 읽기를 해야 함 이 DB의 경우 물리 읽기 1회 당 1ms~5ms 정도 소요되므로, 10000건의 계좌를 읽는데, (DB 서버 구간에서만) 10~50초가 소요될 수 있음 개선 방안 계좌가 많은 ...