본문 바로가기
Web Programming/DB

[ORACLE/오라클] EXISTS, NOT EXISTS, 조건절 서브쿼리 성능(속도) 개선

by jaey0ng 2023. 6. 14.

개선 전: 4n초
개선 후: 1.n초
로 약 40초가량 성능이 개선된 경험을 토대로 글을 작성합니다.

EXISTS 개선
개선 전 코드입니다

AND EXISTS (SELECT 1
              FROM TBL1 A
             WHERE 1=1
               AND A.COL = (SELECT MIN(B.COL B)
                              FROM TBL2 B
                             WHERE 1=1
                               AND #{ROW} IS NOT NULL AND B.ROW = #{ROW}
                           )
               AND ~~
               AND ~~
            )


위 코드 중

AND A.COL = (SELECT MIN(B.COL B)
               FROM TBL2 B
              WHERE 1=1
                AND #{ROW} IS NOT NULL AND B.ROW = #{ROW}
            )

가 원인이 되었습니다.

서브쿼리에 조건을 걸어둬서 빠를 것이라고 예상했지만
처리순서가 후순위 처리가 되어 절차가 늘어나면서 느려진 것으로 예상됩니다…

개선 후 코드입니다

AND EXISTS (SELECT 1
              FROM TBL1 A
                 , (SELECT MIN(B.COL) AS COL
                         , B.ROW
                      FROM TBL2 B
                     WHERE 1=1
                       AND #{ROW} IS NOT NULL AND B.ROW = #{ROW}
                     GROUP BY COL
                            , B.ROW
                   ) B
             WHERE 1=1
               AND A.COL = B.COL
               AND ~~
               AND ~~
           )


조건절 서브쿼리에서
조인문으로 바꾸면서 개선된 케이스입니다.

NOT EXISTS 개선
개선 전 코드입니다

AND NOT EXISTS (SELECT 1
                  FROM TBL1 A
                 WHERE 1=1
                   AND A.COL = (SELECT MIN(B.COL B)
                                  FROM TBL2 B
                                 WHERE 1=1
                                   AND #{ROW} IS NOT NULL AND B.ROW = #{ROW}
                               )
                   AND ~~
                   AND ~~
                )

원인은 EXISTS와 동일합니다.

개선 후 코드입니다

AND NOT EXISTS (SELECT 1
                  FROM TBL1 A
                     , (SELECT MIN(B.COL) AS COL
                             , B.ROW
                          FROM TBL2 B
                         WHERE 1=1
                           AND #{ROW} IS NOT NULL AND B.ROW = #{ROW}
                         GROUP BY COL
                                , B.ROW
                       ) B
                 WHERE 1=1
                   AND A.COL = B.COL
                   AND B.COL IS NULL
                   AND ~~
               )

실제 쿼리는 다르게 쓰일 수 있으나
중요한 것은 조건절에

AND B.COL IS NULL

입니다.

테이블 간 조인을 걸고
존재하지 않아야 하는 컬럼을
조건절에 ~~ IS NULL을 걸면 속도가 개선됩니다.


추가로
TBL1 테이블에는 COL, ROW 2 컬럼만 존재한다는 가정하에

SELECT *
  FROM TBL1 A
 WHERE 1=1
   AND ~~

위 코드처럼
* 을 쓰면 속도가 느려지므로

SELECT A.COL
     , A.ROW
  FROM TBL1 A
 WHERE 1=1

로 필요한 컬럼을 직접 쓰는 것이 속도나 성능에선 더 좋습니다