티스토리 뷰

Database/Oracle

[오라클] OR 연산 성능 튜닝

데브포유 2009. 6. 5. 12:44
반응형

대량의 데이터를 처리할 경우 OR 연산이 조건에 있으면 성능 저하에 많은 영향을 줍니다. 특히 OR 조건중 어느  하나라도 인텍스가 없으면 FULL TABLE SCAN으로 풀리기
쉽죠. OR 연산을 튜닝하는 방법을 몇가지 소개해 드립니다.

예제)
매출테이블(T_TRADE)에서 상점(ID: A, B) 인 상점의 특정 거래일(TR_DT) 동안의 총 매출액(AMT)를 구하라.


1. OR 조건을 UNION ALL로 풀어냄

 : 쉽게 작성할 수 있으나 SQL이 풀어낸 개수만큼 늘어나 유지보수가 어려움.

 SELECT ID, SUM(AMT)
 FROM
 (
  SELECT AMT
  FROM T_TRADE
  WHERE TR_DT IN (SELECT DT FROM COPY_YMD_T WHERE DT BETWEEN '시작일' AND '종료일') -- 선분조건 튜닝
    AND ID = 'A'
     UNION ALL 
     SELECT AMT
  FROM T_TRADE
  WHERE TR_DT IN (SELECT DT FROM COPY_YMD_T WHERE DT BETWEEN '시작일' AND '종료일')
    AND ID = 'B'
  )
  GROUP BY ID
 
2. CONCATENATION 으로 푸는 방법

 SELECT ID, SUM(AMT)
 FROM
 (
  SELECT /*+ use_concat */ AMT
  FROM T_TRADE
  WHERE TR_DT IN (SELECT DT
                  FROM COPY_YMD_T
                  WHERE DT BETWEEN '시작일' AND '종료일'
                    AND ROWNUM >= '0') -- ROWNUM >= '0'은 이 쿼리가 먼저 실행 되도
                                                        록 하기 위해서임. GROUP BY DT를
                                                        사용해도 동일한 효과를 낼 수 있음. 
                                                        단 DT는 INDEX가 있어야 함.
    AND ID IN('A','B')   
  )
  GROUP BY ID  
 
 3. IN의 변형
 SELECT ID, SUM(AMT)
 FROM
 (
  SELECT /*+ use_concat */ AMT
  FROM T_TRADE
  WHERE TR_DT IN (SELECT DT
                  FROM COPY_YMD_T
                  WHERE DT BETWEEN '시작일' AND '종료일'
                    AND ROWNUM >= '0') -- ROWNUM >= '0'은 이 쿼리가 먼저 실행 되도록 하기 위해서임. GROUP BY DT를
                                                       사용해도 동일한 효과를 낼 수 있음. 단 DT는 INDEX가 있어야 함.
    AND ID IN (SELECT ID
               FROM
               (  SELECT 'A' FROM DUAL
                  UNION ALL
                  SELECT 'B' FROM DUAL
               )   -- IN을 변형함으로써 실행계획을 바꿔 성능을 튜닝할 수 있음.
  )
  GROUP BY ID 


 4. DECODE문을 이용하는 방법

  : 위 조건에서는 스위칭성 조건이 없어서 사용할 수 없으나 스위칭성 조건이 있는 OR일 경우 매우 강력한 방법임
    A = DECODE(:SW, '1','A',''B') 같이 OR를 = 조건으로 바꿀 수가 있음.

PS. 방법 3은 아직 정확한 이유를 모르고 우연히 발견한 것으로  IN ('A',''B') 와 뭐가
    다른지 모르겠더군요. 더 연구가 필요합니다. ㅎㅎ
    혹시 이유를 아시는 분은 댓글을 달아 주세요.

반응형