📦
signature-hyeon's tech blog
  • Intro
  • TECH
    • DATABASE
      • MongoDB
    • DEVOPS
      • 배포 전략 (Rolling, Blue/Green, Canary)
    • BACKEND
      • “왜 이렇게 느려?”를 마주했을 때
      • Resilience4j CircuitBreaker
  • STUDY
    • ELASTICSEARCH
      • Elasticsearch 란?
      • 색인과 검색 원리
    • 클린 코드
      • 3장 함수
    • 친절한 SQL 튜닝
      • 1장 SQL 처리 과정과 I/O
      • 2장 인덱스 기본
      • 3.3장 인덱스 스캔 효율화
      • 4.2장 소트 머지 조인
      • 4.3장 해시 조인
      • 5장 소트 튜닝
      • 5.4장 Sort Area 효율적으로 쓰는 SQL 작성법
      • 7장 SQL 옵티마이저
Powered by GitBook
On this page
  1. STUDY
  2. 친절한 SQL 튜닝

5.4장 Sort Area 효율적으로 쓰는 SQL 작성법

친절한 SQL 튜닝 5.4장

Previous5장 소트 튜닝Next7장 SQL 옵티마이저

Last updated 1 month ago

CtrlK
  • 1. Sort 데이터 줄이기
  • 2. Top-N 쿼리는 정렬을 ‘다’ 하지 않는다
  • 3. Top-N 조건이 없으면 정렬은 끝까지 수행된다

스터디하면서 알게 된 정렬 관련 실전 팁을 정리했다. 불필요한 sort area 사용을 줄이기 위한 실제 쿼리 튜닝 사례 위주다.

1. Sort 데이터 줄이기

다음 두 쿼리는 결과는 같지만, 정렬 대상과 시점이 다르다.

-- (1) 가공 후 정렬
SELECT LPAD(상품번호, 30) || LPAD(상품명, 30) || LPAD(고객ID, 30) || LPAD(고객명, 30) || TO_CHAR(주문일시, 'yyyymmdd hh24:mi:ss')
FROM 주문상품
WHERE 주문일시 BETWEEN :START AND :END
ORDER BY 상품번호;
-- (2) 정렬 후 가공
SELECT LPAD(상품번호, 30) || LPAD(상품명, 30) || LPAD(고객ID, 30) || LPAD(고객명, 30) || TO_CHAR(주문일시, 'yyyymmdd hh24:mi:ss')
FROM (
  SELECT 상품번호, 상품명, 고객ID, 고객명, 주문일시
  FROM 주문상품
  WHERE 주문일시 BETWEEN :START AND :END
  ORDER BY 상품번호
);
  • 첫 번째 쿼리는 LPAD와 TO_CHAR로 가공한 후 정렬하기 때문에, 가공된 긴 문자열 전체를 sort area에 적재하게 된다.

  • 두 번째 쿼리는 정렬 후 가공하므로, 정렬 시점의 데이터 양이 작아져 sort area 사용량이 줄어든다.

단순 예시로 다음도 마찬가지다.

-- 전체 컬럼 정렬
SELECT * FROM 예수금원장 ORDER BY 총예수금 DESC;

-- 필요한 컬럼만 정렬
SELECT 계좌번호, 총예수금 FROM 예수금원장 ORDER BY 총예수금 DESC;

→ 정렬 시 불필요한 컬럼을 빼는 것만으로도 sort I/O를 줄일 수 있다.

2. Top-N 쿼리는 정렬을 ‘다’ 하지 않는다

Top-N 쿼리에서는 Oracle이 일반 정렬이 아닌, Top-N Sort 알고리즘을 사용한다.

작동 방식은 다음과 같다

  1. 처음 N개의 레코드를 읽어 정렬

  2. 이후 레코드를 하나씩 읽으면서 N등보다 크면 삽입, 가장 작은 값은 제거

  3. 최종적으로 N개의 레코드만 남긴다

-- Oracle 12c 이상
SELECT * FROM 주문상품 ORDER BY 주문금액 DESC FETCH FIRST 5 ROWS ONLY;

-- Oracle 11g 이하
SELECT * FROM (
  SELECT * FROM 주문상품 ORDER BY 주문금액 DESC
) WHERE ROWNUM <= 5;

장점

  • 전체 정렬이 아니므로 메모리 사용량이 적다

  • 인덱스로 소트 연산을 생략할 수 없어 Table Full Scan 방식 시 SORT ORDER BY STOPKEY 를 사용한다.

3. Top-N 조건이 없으면 정렬은 끝까지 수행된다

ROWNUM 또는 FETCH FIRST 조건이 없는 경우, 전체 데이터를 정렬해야 하므로 sort 부하가 커질 수 있다.

-- 정렬 대상이 많아질수록 부하 커짐
SELECT * FROM 주문상품 ORDER BY 주문금액 DESC;

또한 다음과 같은 윈도우 함수는 MAX()보다 효율적인 정렬을 할 수 있다.

  • RANK(), ROW_NUMBER() → 내부적으로 Top-N 정렬 사용