
정렬(Sort)은 DB에서 가장 비용이 큰 연산 중 하나다.

이유
결론
소트는 가능하면 발생하지 않도록,
발생하더라도 메모리 안에서 끝나도록 해야 한다.
실행 계획에 표시되는 주요 Sort 연산들
전체 집계를 수행할 때 발생
(MIN, MAX, SUM, AVG 등)
SELECT MAX(sal) FROM emp;
ORDER BY가 있을 때 발생하는 정렬
SELECT * FROM emp ORDER BY sal DESC;
GROUP BY가 있을 때 발생
SELECT deptno, MAX(sal)
FROM emp
GROUP BY deptno
ORDER BY deptno;
ORDER BY가 없으면 Sort Group By는 발생하지 않을 수 있다.
→ Hash Group By로 최적화됨
Hash Group By 동작
중복 제거 시 발생하는 소트
IN 서브쿼리 중복 제거
SELECT * FROM dept
WHERE deptno IN (SELECT deptno FROM emp);
UNION
SELECT job FROM emp WHERE deptno=10
UNION
SELECT job FROM emp WHERE deptno=20;
중복 제거 시 정렬이 필요한 이유
데이터가 멀리 떨어져 있는 경우 모든 값을 기억해야 중복인지 판단할 수 있음
→ 메모리 한번 스캔으로는 안됨.
→ 메모리 폭발
정렬하면?
→ 직전 값과 같은지 비교만 하면 중복 판단 가능
→ 정렬하면 중복 판단이 O(1) 공간으로 가능
→ 정렬이 없으면 O(N) 메모리 필요
Sort Merge Join에서 발생하는 정렬
각 테이블을 조인키 기준으로 정렬한 뒤 Merge
TABLE A SORT (JOIN)
TABLE B SORT (JOIN)
MERGE JOIN
윈도우 함수(행과 행 간의 관계를 쉽게 정의 및 분석하는 함수) 실행 시 발생
SELECT mgr, ename, sal,
SUM(sal) OVER (PARTITION BY mgr) mgrsum
FROM emp;
비효율
SELECT ...
UNION
SELECT ...
최적화
SELECT ...
UNION ALL
SELECT ...
핵심
비효율적 DISTINCT
SELECT DISTINCT a.*
FROM A a, B b
WHERE a.x = :x
AND b.y = a.y
AND b.z BETWEEN :dt1 and :dt2;
→ B 를 모두 읽고 → DISTINCT로 중복 제거 → Sort Unique 발생
최적화 EXISTS 활용
SELECT a.*
FROM A a
WHERE a.x = :x
AND EXISTS (
SELECT 1 FROM B b
WHERE b.y = a.y
AND b.z BETWEEN :dt1 AND :dt2
);
중복 제거 필요 없음
EXISTS 는 존재 여부만 판단 → 매우 효율적
소트 제거 가능
Hash Join = 내부적으로 소트 & 버퍼 사용
NL Join = 인덱스 기반 랜덤 I/O
정렬 없이 ORDER BY / GROUP BY / MIN / MAX를 처리할 수 있다면
인덱스를 이용한 최적화가 가능하다는 뜻이다.
SELECT *
FROM emp
ORDER BY sal DESC
FETCH FIRST 10 ROWS ONLY;
인덱스가 있다면
정렬 없이 인덱스 정순/역순 스캔으로 10개만 읽고 중단
→ STOPKEY 알고리즘
→ 실행 계획: COUNT(STOPKEY)
SELECT MIN(sal) FROM emp;
인덱스(sal asc) 가 있다면
조건절 컬럼 + MIN/MAX 대상 컬럼 모두 인덱스에 포함되어 있어야 함
SELECT region, AVG(age)
FROM customer
GROUP BY region;
region 컬럼이 선두 컬럼 인덱스면
GROUP BY 수행 시 이미 정렬되어있음
Sort Group By → Sort Group By (NOSORT)로 변경됨
정렬 사라짐
소트가 불가피하다면
Sort Area에 최대한 적은 데이터를 넣게 만들어서 Temporary Table 사용을 줄여라
비효율
SELECT *
FROM emp
ORDER BY age;
Sort Area 에 전체 컬럼이 들어가므로 메모리 사용량 ↑
효율적
SELECT name
FROM emp
ORDER BY age;
필요한 컬럼만 Sort → Sort Area 사용량 ↓
메모리 안에서 끝날 확률 ↑
TOP-N 쿼리는 소트가 필요하더라도
Top-N은 인덱스를 못 타더라도 메모리 친화적