본문 바로가기
카테고리 없음

GROUP BY, DISTINCT, ORDER BY 최적화 방법 총정리

by 유형제맘 2025. 8. 12.

SQL에서 GROUP BY, DISTINCT, ORDER BY는 데이터 집계나 정렬을 위해 자주 사용되는 구문입니다. 하지만 대용량 데이터에서 무심코 사용하면 성능이 급격히 저하될 수 있습니다. 오늘은 각 구문이 어떻게 동작하는지, 그리고 어떻게 최적화할 수 있는지 살펴보겠습니다.

GROUP BY 최적화

GROUP BY는 동일한 값을 가진 행들을 그룹화하여 집계 연산을 수행합니다.
1) 기본 동작 방식

  • 서버는 대상 컬럼을 기준으로 데이터를 정렬(SORT)한 후 그룹핑 처리
  • 집계 함수(SUM, COUNT, AVG 등)와 함께 사용
SELECT category, COUNT(*) AS cnt
FROM products
GROUP BY category;

 

2) 성능 저하 원인

  • 정렬(Sort) 작업이 추가적으로 발생
  • 데이터가 많을수록 메모리/디스크 사용량 급증

3) 최적화 방법

인덱스 활용

  • 그룹핑 대상 컬럼에 적합한 인덱스를 생성하면 정렬 작업을 줄일 수 있음
CREATE INDEX idx_products_category ON products(category);

 

GROUP BY와 WHERE 조합

  • 먼저 WHERE로 데이터 범위를 줄인 후 GROUP BY 수행
SELECT category, COUNT(*)
FROM products
WHERE status = 'active'
GROUP BY category;

 

중간 집계 테이블 활용

  • 실시간이 필요 없는 경우 미리 집계한 결과를 저장한 테이블 사용

DISTINCT 최적화

DISTINCT는 중복 행을 제거합니다.
1) 기본 동작 방식

  • 내부적으로 GROUP BY와 유사하게 동작 (중복을 제거하기 위해 정렬 또는 해시 처리)
SELECT DISTINCT category
FROM products;

 

 

2) 성능 저하 원인

  • 불필요한 컬럼 포함 시 불필요한 정렬 및 비교 연산 발생
  • 대량 데이터에서 메모리 사용량 증가

3) 최적화 방법

  • 필요한 컬럼만 SELECT
  • DISTINCT 대상 컬럼만 포함하여 불필요한 데이터 처리 방지
--  비효율
SELECT DISTINCT * FROM products;

-- 효율적 
SELECT DISTINCT category FROM products;


인덱스 이용

  • DISTINCT 컬럼에 인덱스를 걸면 중복 제거 속도가 빨라짐

EXISTS 또는 JOIN으로 대체

  • DISTINCT 대신 EXISTS로 중복 제거 로직을 대체하는 경우가 있음
SELECT category
FROM products p
WHERE EXISTS (
SELECT 1
FROM categories c
WHERE c.id = p.category_id
);

ORDER BY 최적화

ORDER BY는 결과 집합을 특정 컬럼 기준으로 정렬합니다.
1) 성능 저하 원인

  • 데이터 정렬은 많은 CPU와 메모리를 사용
  • 인덱스를 사용하지 못하면 Filesort 발생 → 성능 저하

2) 최적화 방법

  • 인덱스 순서와 동일하게 ORDER BY
-- 인덱스 생성
CREATE INDEX idx_products_price ON products(price);

-- 인덱스를 활용한 정렬
SELECT * FROM products ORDER BY price;


LIMIT와 함께 사용

  • 전체 데이터 정렬 대신 필요한 범위만 정렬
SELECT * FROM products ORDER BY price LIMIT 10;


정렬 컬럼 최소화

  • 여러 컬럼을 정렬할 경우 인덱스 복합 구성 고려

커버링 인덱스(Covering Index) 활용

  • SELECT 컬럼과 ORDER BY 컬럼이 인덱스에 모두 포함되면 디스크 I/O 감소

실행 계획(Execution Plan)으로 확인

GROUP BY, DISTINCT, ORDER BY 최적화 여부를 확인하려면 EXPLAIN으로 실행 계획을 분석합니다.

EXPLAIN SELECT category, COUNT(*)
FROM products
GROUP BY category;

 

  • Using index → 인덱스를 사용 중
  • Using temporary; Using filesort → 임시 테이블 및 디스크 정렬 발생 (개선 필요)

정리

  • GROUP BY: 인덱스를 적극 활용하고, 데이터 범위를 줄인 후 그룹화
  • DISTINCT: 불필요한 컬럼 제거, 인덱스 사용, EXISTS 대체 가능
  • ORDER BY: 인덱스 순서와 동일하게 정렬, LIMIT 사용
  • 실행 계획을 통해 항상 병목 지점을 파악할 것