IT 서적/친절한 SQL 튜닝

12. 친절한 SQL 튜닝

SH.DevBlog 2023. 10. 21. 20:52
728x90

소트가 발생하지 않도록 SQL 작성

UNION VS UNION ALL

  • UNION을 사용하면 옵티마이저는 상단과 하단 두 집합 간 중복을 제거하려고 소트 작업을 수행
  • UNION ALL은 중복을 확인하지 않고 두 집합을 단순히 결합
  • 따라서, 특이한 케이스를 제외하고는 UNION ALL을 사용하는 것이 효율적이다.

UNION ALL을 사용하려면 아래와 같이 쿼리를 작성해야 한다.

SELECT 결제번호
      ,결제수단코드
      ,주문번호
      ,결제금액
  FROM 결제
  WHERE 결제일자 = '20180316'
  
  UNION ALL
  
SELECT 결제번호
      ,결제수단코드
      ,주문번호
      ,결제금액
  FROM 결제
  WHERE 주문일자 = '20180316'
    AND 결제일자 <> '20180316'

만약에 결제일자가 'NULLABLE'로 설계돼 있다면 아래 조건을 추가해야 한다.

AND (결제일자 <> '20180316' OR 결제일자 IS NULL)'
LNNVL(결제일자 = '20180316')
  • LNNVL 함수는 아래의 상황일 때 조건이 TRUE이다.
    컬럼이 NULL인 경우 = TRUE
    함수 내부 조건이 FALSE인 경우 = TRUE

EXIST 활용

  • 중복 데이터를 제거할 목적으로 DISTINCT 연산자를 종종 사용하는데, 이 연산자를 사용할 경우 모든 데이터를 읽어서 중복을 제거해야 한다.
  • 모든 데이터를 읽는 과정에서는 무분별한 I/O가 발생하게 된다.
SELECT DISTINCT 
       P.상품번호
      ,P.상품명
      ,P.상품가격
  FROM 상품 P
      ,계약 C
  
  WHERE P.상품유형코드 = :pclscd
    AND C.상품번호 = P.상품번호
    AND C.계약일자 BETWEEN :dt1 AND :dt2
    AND C.계약구분코드 = :ctpcd
  • 위 쿼리를 아래와 같이 바꿔보자.
SELECT P.상품번호
      ,P.상품명
      ,P.상품가격
  FROM 상품 P
  
  WHERE P.상품유형코드 = :pclscd
    AND EXIST (
               SELECT 'X' 
                 FROM 계약 C
                 WHERE C.상품번호 = P.상품번호
                   AND C.계약일자 BETWEEN :dt1 AND :dt2
                   AND C.계약구분코드 = :ctpcd
              )
  • EXIST 서브쿼리는 데이터 존재 여부만 확인하기 때문에 조건절을 만족하는 데이터를 모두 읽지 않는다.
728x90