권순용의 DB 이야기
SQL 작성시 ROWID 활용 0 0 3,549

by axiom ROWID ROWID활용 [2015.10.18]


지난 시간에는 ROWID의 이용에 대해 살펴봤다. 이 글에서는 ROWID는 다양한 곳에 사용할 수 있는 분량 관계상 소개하지 못한 ROWID의 또 다른 활용 방안을 소개한다.

ROWID를 이용한 조인 방식은 사용자가 직접 변경할 수도 있다. <리스트 1>을 살펴보자.

  • [리스트 1] ROWID 조인 방식 확인
  • SELECT A.COL1, B.COL2
      FROM TAB1 A, TAB2 B
     WHERE A.KEY1 BETWEEN B.KEY2 AND B.KEY3;
    

<리스트 1>의 TAB1 테이블과 TAB2 테이블은 조인을 이용해 데이터를 추출한다. 조인 조건이 ‘=’이 아닌 BETWEEN 조건을 사용하고 있는데, 이 경우 조인 방식 중 중첩 루프 조인만 사용 가능하다. 해당 SQL에 대해 해시 조인을 이용해야 한다면 <리스트 2>처럼 SQL을 변경해야 한다.

  • [리스트 2] 조인 방식을 해시 조인으로 변경
  • SELECT A.COL1, B.COL2
      FROM TAB1 A, TAB2 B
     WHERE A.KEY1 BETWEEN B.KEY2 AND B.KEY3
       AND LENGTH(A.ROWID) = LENGTH(B.ROWID);
    

해시 조인은 ‘=’ 조인에서만 적용 가능하다. 그러므로 TAB1과 TAB2 테이블 모두에 ROWID가 존재하며, ROWID는 길이가 동일하므로 <리스트 2>처럼 SQL을 변경하면 동일한 결과가 추출된다. ROWID를 활용하면 해시 조인을 적용 가능한 것이다.

조인 방식

조인 방식으로는 다음과 같이 세 가지 방식이 있다.

  • - 중첩 루프 조인(NESTED LOOPS JOIN)
  • - 해쉬 조인(HASH JOIN)
  • - 소트 머지 조인(SORT MERGE JOIN)

각각의 조인 방식에 대해서는 다음 시간에 다룰 ‘조인’ 시간에 자세히 살펴본다.

게시판 등에 많이 사용되는 목록 쿼리에서도 ROWID를 활용할 수 있다.

  • [리스트 3] 목록 쿼리 SQL 예
  • SELECT 순번, 종류, 제목, 도착시간, 크기
      FROM
         ( SELECT ROWNUM 순번, 종류, 제목, 도착시간, 크기
             FROM 
                ( SELECT /*+ INDEX(메일,메일아이디_도착시간_IDX) */
                         메일.종류, 메일.제목, 메일.도착시간, 메일.크기
                    FROM 메일
                   WHERE 메일_아이디 = ‘KKK’
                   ORDER BY 도착시간 DESC
                )
         )
     WHERE 순번 BETWEEN 381 AND 400
       AND ROWNUM < = 20
    

<리스트 3>의 SQL은 게시판을 구성하는 목록 쿼리의 예다. 하나의 화면에 20건의 데이터를 보여주는데, 여기에 ROWID를 적용하면 쿼리 처리 성능을 높일 수 있다.

인덱스와 테이블을 엑세스하는 부분은 랜덤 엑세스(random access)라고 한다. 이러한 랜덤 엑세스는 성능 저하의 주범이지만 이를 제거한다는 것은 결코 쉬운 일이 아니다.

  • [리스트 4] 목록 쿼리 가장 안쪽의 SQL
  • SELECT /*+ INDEX(메일,메일아이디_도착시간_IDX) */
           메일.종류, 메일.제목, 메일.도착시간, 메일.크기
      FROM 메일
     WHERE 메일_아이디 = 'KKK'
     ORDER BY 도착시간 DESC
    

인덱스는 <리스트 4>의 SQL을 위해 메일_아이디+도착시간 인덱스를 가지고 있다. 이처럼 인덱스를 구성하면 메일_아이디+도착시간 인덱스를 엑세스한 다음 메일 테이블을 엑세스해야 하는데, 이때 랜덤 엑세스가 발생하게 된다. 해당 SQL에서 랜덤 엑세스를 제거하고 싶다면 인덱스를 다음과 같이 생성해야 한다.

메일_아이디 + 도착시간 + 종류 + 제목 + 크기

이처럼 인덱스를 생성하면 인덱스에 원하는 컬럼이 모두 존재하므로 인덱스 엑세스 후 메일 테이블을 엑세스할 필요가 없다. 즉 랜덤 엑세스가 제거된 것이다. 하지만 이처럼 컬럼의 개수를 무작정 늘리는 것에는 부담이 뒤따른다. 이런 경우에도 ROWID가 유용하게 쓰인다.

  • [리스트 5] 목록 쿼리에 ROWID 적용
  • SELECT /*+ USE_NL(A B) */ 
           A.순번, B.종류, B.제목, B.도착시간, B.크기
      FROM 
         ( SELECT 순번, RID
            FROM 
               ( SELECT ROWNUM 순번, RID
                   FROM 
                       ( SELECT /*+ INDEX(메일,메일아이디_도착시간_IDX) */
                                ROWID
                           FROM 메일
                          WHERE 메일_아이디 = ‘KKK’
                          ORDER BY 도착시간 DESC
                        )
               )
           WHERE 순번 BETWEEN 381 AND 400
             AND ROWNUM < = 20
         ) A,
           메일 B
     WHERE A.RID = B.ROWID;
    

<리스트 5> SQL을 수행하는 경우를 따져보자. 인라인 뷰 A는 메일_아이디_도착시간 인덱스만 이용한다면 원하는 데이터가 모두 인덱스에 있으므로 테이블을 엑세스할 때 랜덤 엑세스가 발생하지 않는다.

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

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

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

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