SQL) 소트 튜닝 Ⅱ

jinsung·2026년 1월 12일
post-thumbnail

3. 데이터 모델 측면에서의 검토

불합리한 데이터 모델이 소트 오퍼레이션을 유발하는 경우를 흔히 접할 수 있다.

✅ 사례 1 - M:M 관계를 갖도록 설계된 테이블

한쪽을 group by 해서 1:M 관계로 만들어주었지만 과거 데이터이관 시 발생한 예외 케이스 때문에 다시 M:M 모델이 되었다고 한다.

=> 데이터를 정제하고 1:M 관계를 갖도록 모델을 수정하였다.
그 결과, 불필요한 group by 연산을 제거할 수 있어 쿼리가 간단해지고 성능도 좋아졌다.

✅ 사례 2 - 자식 테이블에 통합시키는 경우

그 테이블의 조회가 빈번하다면, 조회할 때마다 테이블을 group by 해야 하기 때문에 성능이 좋을 리 없다.


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

union을 사용한 쿼리는 두 집합 간 중복을 제거하려고 sort unique 연산을 수행한다.
만약 결과 값에 PK 컬럼을 포함하면 중복은 무조건 없기 때문에 union all 을 사용해야 한다.
union all은 중복을 확인하지 않고 두 집합을 단순히 결합하므로 소트 부하가 없기 때문이다.

distinct를 사용하는 경우도 대부분 exists 서브쿼리로 대체함으로써 소트 연산을 없앨 수 있다.
소량의 데이터를 가지는 테이블을 Outer 테이블로 지정해 큰 테이블을 exists 서브쿼리로 필터링하는 방식을 사용하면 된다.
여기서 exists 서브쿼리의 가장 큰 특징은, 메인 쿼리로부터 건건이 입력 받은 값에 대한 조건을 만족하는 첫 번째 레코드를 만나는 순간 true를 반환하고 서브쿼리 수행을 마친다는 점이다.
=> 따라서 서브쿼리의 조건절에 맞게 인덱스만 구성해주면 최적으로 수행된다.


5. 인덱스를 이용한 소트 연산 대체

인덱스는 항상 키 컬럼 순으로 정렬된 상태를 유지하므로 이를 이용해 소트 오퍼레이션을 생략할 수 있다.

1. Sort Order By 대체

select custid, name, resno, status, tell
from customer
where region = 'A'
order by custid

위 쿼리를 수행할 때 [region + custid] 순으로 구성된 인덱스를 사용한다면 sort order by를 대체 할 수 있다.

이 방식으로 수행한다면 region = 'A' 조건을 만족하는 전체 로우를 읽지 않고도 결과집합 출력을 시작할 수 있어 OLTP 환경에서 극적인 성능 개선 효과를 가져다 준다.

물론, 소트해야 할 대상 레코드가 무수히 많고 그 중 일부만 읽고 멈출 수 있는 업무에서만 이 방식이 유리하다.

2. Sort Group By 대체

select region, avg(age), count(*)
from customer
group by region

region이 선두 컬럼인 결합 인덱스나 단일 컬럼 인덱스를 사용한다면 위 쿼리에 필요한 sort group by 연산을 대체할 수 있다. (실행계획은 sort group by nosort 표기)

인덱스를 이용한 nosort 방식으로 수행될 때는 group by 오퍼레이션에도 불구하고 부분범위처리가 가능해져 OLTP 환경에서 매우 극적인 성능 개선 효과를 얻을 수 있다.

3. 인덱스가 소트 연산을 대체하지 못하는 경우

select *
from emp
order by sal

만약 sal을 선두로 시작하는 인덱스가 있는 경우에도 sal을 기준으로 정렬을 하게된다면,
옵티마이저는 인덱스를 사용하지 않는 편이 낫다고 판단 해 all_rows 모드를 선택한다.

create index emp_deptno_sql on emp(deptpno,sal);

select *
from emp
where deptno = 10
order by sal null first  

위의 경우도 소트 오퍼레이션이 나타난다.
단일 인덱스일 때는 null 값을 저장하지 않지만, 결합 인덱스일 때는 null 값을 가진 레코드를 맨 뒤에 저장한다.
따라서 null 값부터 출력하려고 할 떄는 인덱스를 이용하더라도 소트가 발생한다.

profile
Data Engineer

0개의 댓글