소트조인(2/4)

Posted by : on

Category : sql_tuning


5.2 소트 발생을 방지하는 SQL 작성

SQL을 작성할 때는 소트(Sort) 연산이 발생하지 않도록 주의해야 합니다.

Union, Minus, Distinct 연산자는 중복 레코드를 제거하기 위해 소트 연산을 수행하므로, 필요한 경우에만 사용해야 합니다.

5.2.1 Union | Union All

UNION을 사용하면 옵티마이저가 상위와 하위 두 집합 간의 중복을 제거하기 위해 소트 작업을 수행합니다. 반면, UNION ALL은 중복을 확인하지 않고 두 집합을 단순히 결합하므로 소트 작업이 발생하지 않습니다.

가능하면 UNION ALL을 사용하는 것이 좋습니다. 단, UNIONUNION ALL로 변경하면 결과 집합이 달라질 수 있으므로 신중하게 판단해야 합니다.

아래 SQL은 UNION 상위와 하위 집합 사이에 인스턴스 중복 가능성이 없으므로 UNION ALL을 사용하는 것이 효과적입니다.

SELECT 결제번호, ...
FROM 결제
WHERE 결제수단코드 = 'M' AND 결제일자 = '20200101'
UNION ALL
SELECT 결제번호, ...
FROM 결제
WHERE 결제수단코드 = 'C' AND 결제일자 = '20200101'

아래 SQL은 UNION 상위와 하위 집합 사이에 인스턴스 중복 가능성이 있습니다.

SELECT 결제번호, ...
FROM 결제
WHERE 결제일자 = '20200101'
UNION
SELECT 결제번호, ...
FROM 결제
WHERE 주문일자 = '20200101'

0 1 SELECT STATEMENT 1 0 SORT(UNIQUE) … 2 1 UNION-ALL …. 결제일자와 주문일자 조건은 상호 배타적이지 않기 때문에 중복이 발생할 수 있습니다.

소트 연산이 발생하지 않도록 하기 위해서는 다음과 같이 작성할 수 있습니다.

SELECT 결제번호, ...
FROM 결제
WHERE 결제일자 = '20200101'
UNION ALL
SELECT 결제번호, ...
FROM 결제
WHERE 주문일자 = '20200101'
  AND 결제일자 <> '20200101'

0 1 SELECT STATEMENT 1 0 UNION-ALL 2 1 TABLE ACCESS … 3 2 INDEX (RANGE SCAN).. 4 1 TABLE ACCESS .. 5 4 INDEX .. ….

다만, 결제일자가 NULL을 허용하는 경우 조건절을 다음과 같이 변경해야 합니다.

AND (결제일자 <> '20200101' OR 결제일자 IS NULL)

또는 LNNVL 함수를 사용하여 다음과 같이 작성할 수 있습니다.

AND LNNVL(결제일자 = '20230101')

5.2.2 Exists 활용 중복 레코드를 제거하기 위해 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, 계약 c
WHERE p.상품유형코드 = :pclscd
  AND EXISTS (
    SELECT 'x'
    FROM 계약 c
    WHERE c.상품번호 = p.상품번호
      AND c.계약일자 BETWEEN :dt1 AND :dt2
      AND c.계약구분코드 = :ctpcd
  )

DISTINCT를 사용하지 않았으므로 부분 범위 처리가 가능해집니다.

MINUS 연산자의 경우, NOT EXISTS 서브쿼리로 변경할 수 있습니다.

5.2.3 조인 방식 변경 SORT (ORDER BY)가 발생하는 경우, 인덱스를 이용해 소트 연산을 생략할 수 있습니다. NL(Nested Loop) 조인 방식을 사용하도록 조인 방식을 변경하면 최소한의 연산을 생략할 수 있어 부분 범위 처리가 가능해져 성능이 크게 향상됩니다.

SELECT /*+ LEADING(c) USE_NL(p) */
       c.계약번호, ...
FROM 계약 c, 상품 p
WHERE ...

About GoldTree
GoldTree

안녕하세요.

Email : gold@onetreegold.com

Website : https://onetreegold.com

About GoldTree

Java, Web, Db

Categories
Useful Links