SQL 튜닝의 시작

  • 튜닝의 시작은 SQL의 의미를 파악하는 것
  • 단순히 I/O 발생량을 줄인다거나 수행시간을 단축하기 위해 힌트를 남발하는 것은 상당히 위험한 일이다

예제) 인덱스의 구조

INDEX NAMECOLUMN_LIST
INDEX_MBOX_STATUSUSERID, STATUS
INDEX_MBOX_SENDDATAUSERID, SENDDATE





SELECT *
  FROM (SELECT /*+ INDEX_DESC(A IDX_MBOX_SENDDATA) */
               A.*,
               ROWNUM AS RNUM
          FROM TBS_MBOX A
         WHERE USERID = :B1
           AND STATUS = :B2
           AND ROWNUM <= :B3
       )
 WHERE RNUM >= :B4;

VIEW
 COUNT STOPKEY
  TABLE ACCESS (BY INDEX ROWID) OF 'TBS_MBOX' (TABLE)
    INDEX (RANGE SCAN DESCENDING) OF 'IDX_MBOX_SENDDATE' (INDEX)

  • 위의 실행계획을 보고 조건절을 모두 충족 시키는 INDEX_MBOX_STATUS인덱스를 이용하게 되면 결과 값이 달라 질 수 있다.
  • 위의 SQL의 의도는 USERID, SENDDATE순으로 DESCENDING 정렬된 데이터를 추출하고자 하는 의도이다.

위의 쿼리를 아래와 같이 변경할 수 있다.


SELECT X.*
  FROM (SELECT A.*,
               ROWNUM AS RNUM
          FROM (SELECT A.*
                  FROM TBS_MBOX A
                 WHERE USERID = :B1
                   AND STATUS = :B2
                 ORDER BY A.USERID DESC, A.SENDDATE DESC
                ) A
         WHERE ROWNUM <= :B3
       ) X
 WHERE RNUM >= :B4;

  • 위 SQL의 개선안 중 하나는 IDX_MBOX_SENDDATE 인덱스에 STATUS 컬럼을 추가하여 재 생성하는 것이다.
  • 위 SQL을 만족하는 가장 최선의 INDEX는 {*}USER_ID + STATUS + SENDDATE{*} 이다.(이 쿼리가 악성 SQL이고 성능에 문제가 많을 경우는 이 인덱스가 가장 최선이다.)


    그러나 이미 USER_ID + SENDDATE 인덱스가 존재하고 위의 인덱스를 점조건으로 사용하는 SQL이 많을 경우에는 {*}USER_ID + SENDDATE + STATUS{*}로 생성할 수도 있다.