반응형
Ant_U
DBA 개미
Ant_U
전체 방문자
오늘
어제
  • 분류 전체보기 (271)
    • AWS (3)
    • C# (1)
    • SQL (245)
      • MYSQL (195)
      • MSSQL (50)
    • 자격증 (20)
      • SQLD (12)
      • SQLP (8)

인기 글

최근 글

250x250
hELLO · Designed By 정상우.
Ant_U

DBA 개미

[MySQL] DISTINCT: 중복된 데이터를 세련되게 처리하는 기술 (기초부터 성능 최적화까지)
SQL/MYSQL

[MySQL] DISTINCT: 중복된 데이터를 세련되게 처리하는 기술 (기초부터 성능 최적화까지)

2026. 1. 29. 09:51
728x90
반응형

 

 

데이터베이스를 다루다 보면 가장 흔하게 마주치는 문제 중 하나가 바로 **'중복 데이터'**입니다. 단순히 "서울에 사는 고객 명단을 뽑아줘"라는 요청을 받았을 때, 동일한 고객이 여러 번 구매했다고 해서 명단에 같은 이름이 수십 번 등장한다면 곤란하겠죠?

이때 등장하는 구세주가 바로 MySQL의 DISTINCT입니다. 오늘은 주니어 개발자에게는 확실한 기초를, 시니어 개발자에게는 성능 최적화와 버전별 동작 차이에 대한 인사이트를 제공하는 MySQL DISTINCT 완전 정복 가이드를 준비했습니다.


1. DISTINCT의 기본: "중복은 거절한다"

가장 직관적인 사용법부터 알아보겠습니다. DISTINCT는 SELECT 문 바로 뒤에 위치하여, 조회 결과에서 중복된 행(Row)을 제거하고 유니크한 값만 남깁니다.

기본 문법과 예제

상상해봅시다. orders 테이블에 고객들이 주문한 내역이 쌓여 있습니다.

SELECT city FROM orders;
-- 결과: 서울, 부산, 서울, 대구, 부산, 서울 ... (중복 발생)

이때 DISTINCT를 사용하면 깔끔하게 정리됩니다.

 

SELECT DISTINCT city FROM orders;
-- 결과: 서울, 부산, 대구 (중복 제거됨)

초보자를 위한 팁: DISTINCT는 특정 컬럼 하나에만 적용되는 함수가 아닙니다. SELECT DISTINCT city, country처럼 여러 컬럼을 나열하면, 나열된 모든 컬럼의 조합이 중복되는 경우를 제거합니다. (즉, city와 country가 '모두' 같아야 중복으로 간주합니다.)


2. DISTINCT와 GROUP BY: 영원한 라이벌?

많은 개발자분들이 면접 질문이나 실무에서 헷갈려 하는 부분입니다. "중복을 제거할 때 GROUP BY를 써도 되는데, 왜 DISTINCT가 따로 있나요?"

결론부터 말씀드리면, "단순 중복 제거"가 목적이라면 DISTINCT가, "집계(Sum, Avg 등)"가 목적이라면 GROUP BY가 적합합니다. 하지만 내부 동작에는 미묘한 차이가 있습니다.

동작 원리의 차이와 버전별 변화 (MySQL 5.7 vs 8.0)

  • MySQL 5.7 및 이전 버전:
    • GROUP BY를 사용하면 그룹핑과 동시에 **암묵적인 정렬(Sorting)**이 발생했습니다. 따라서 정렬이 필요 없는 단순 중복 제거에 GROUP BY를 쓰면 불필요한 정렬 오버헤드가 발생할 수 있었습니다.
    • 반면 DISTINCT는 정렬을 보장하지 않으며 중복만 제거합니다.
  • MySQL 8.0 이후:
    • 중요한 변화: MySQL 8.0부터는 GROUP BY의 암묵적 정렬 기능이 제거되었습니다. 이제 GROUP BY도 정렬을 하려면 반드시 ORDER BY를 명시해야 합니다.
    • 따라서 최신 버전에서는 두 구문의 성능 차이가 줄어들었지만, 코드의 가독성(의도 표현) 측면에서 단순 중복 제거에는 여전히 DISTINCT를 사용하는 것이 권장됩니다.

3. 성능 최적화: 인덱스(Index)라는 날개를 달자

DISTINCT는 공짜가 아닙니다. 데이터베이스는 중복을 찾아내기 위해 내부적으로 **임시 테이블(Temporary Table)**을 생성하거나 데이터를 정렬하는 비싼 작업을 수행합니다. 데이터가 수백만 건이라면 쿼리 속도가 현저히 느려질 수 있습니다.

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

가장 강력한 최적화 방법은 **인덱스만으로 쿼리를 처리하는 것(커버링 인덱스)**입니다.

예를 들어 orders 테이블의 city 컬럼에 인덱스가 걸려 있다고 가정해 봅시다.

-- 인덱스가 없는 경우:
-- 1. 테이블의 모든 데이터를 읽음 (Full Table Scan)
-- 2. 임시 테이블을 만들어 중복 제거 수행
-- -> 느림!

-- 인덱스가 있는 경우 (idx_city):
-- 1. 정렬된 인덱스 트리만 스캔하며 중복을 건너뜀 (Loose Index Scan 등)
-- -> 매우 빠름!

고급 팁: COUNT(DISTINCT column)을 사용할 때도 인덱스의 유무는 성능에 결정적인 영향을 미칩니다. 가능한 한 DISTINCT 대상 컬럼은 인덱스를 태우는 것이 좋습니다.


4. 주의사항: NULL의 함정

DISTINCT를 사용할 때 자주 실수하는 부분이 바로 NULL 값의 처리입니다.

  • 원칙: DISTINCT는 NULL도 하나의 값으로 취급하여 중복을 제거합니다.
  • 결과: 만약 데이터에 NULL이 여러 개 있다면, DISTINCT 결과에는 단 하나의 NULL만 포함됩니다.

반면, COUNT(DISTINCT col)을 사용할 때는 NULL인 행은 카운트에서 제외된다는 점을 기억해야 합니다. 이 미묘한 차이가 통계 데이터의 오차를 만들 수 있습니다.


결론 및 실무 팁

DISTINCT는 간단해 보이지만, 대용량 데이터 환경에서는 성능 병목의 원인이 되기도 합니다.

핵심 요약:

  1. 단순 중복 제거는 DISTINCT, 집계가 필요하면 GROUP BY를 사용하세요.
  2. 인덱스 활용은 필수입니다. DISTINCT 대상 컬럼에 인덱스를 추가하면 임시 테이블 생성을 막고 성능을 비약적으로 높일 수 있습니다.
  3. NULL 처리에 주의하세요. COUNT(DISTINCT)는 NULL을 세지 않습니다.

Next Step for You: 지금 운영 중인 쿼리에서 DISTINCT가 포함된 슬로우 쿼리가 있나요? 해당 컬럼에 인덱스가 적용되어 있는지 EXPLAIN 명령어로 실행 계획을 한 번 확인해 보세요. 작은 인덱스 하나가 극적인 성능 향상을 가져올 수 있습니다.


관련 공식 문서: 더 깊이 있는 내용을 원하신다면 MySQL 공식 문서를 참고하세요. MySQL 8.0 Reference Manual - DISTINCT Optimization

728x90
반응형

'SQL > MYSQL' 카테고리의 다른 글

[MySQL] LIKE 연산자 활용법과 성능 최적화 가이드 (인덱스 활용 및 주의사항)  (0) 2026.02.05
[MySQL] 논리 연산자 완벽 가이드: AND, OR, NOT 제대로 사용하기  (0) 2026.02.03
[MySQL] WHERE 절 완전 정복: 기본 문법부터 8.0 최적화 팁까지  (0) 2026.01.30
[MySQL] 백틱(`)의 역할과 올바른 사용법: 언제 써야 하고, 언제 피해야 할까?  (0) 2026.01.28
[MySQL] 습관적으로 쓴 SELECT * 가 당신의 DB를 느리게 만드는 이유 (feat. 실행 계획 분석)  (0) 2026.01.27
[MySQL] 에러 핸들링의 숨은 조력자: SHOW ERRORS 문 완벽 가이드  (0) 2026.01.26
[MySQL] 스토리지 엔진 확인의 첫걸음: SHOW ENGINES 문법 완벽 가이드  (0) 2026.01.22
[MySQL] SHOW ENGINE 문법 정복: SHOW ENGINE INNODB STATUS로 잠금·데드락·버퍼 이슈 읽어내기  (1) 2026.01.20
    'SQL/MYSQL' 카테고리의 다른 글
    • [MySQL] 논리 연산자 완벽 가이드: AND, OR, NOT 제대로 사용하기
    • [MySQL] WHERE 절 완전 정복: 기본 문법부터 8.0 최적화 팁까지
    • [MySQL] 백틱(`)의 역할과 올바른 사용법: 언제 써야 하고, 언제 피해야 할까?
    • [MySQL] 습관적으로 쓴 SELECT * 가 당신의 DB를 느리게 만드는 이유 (feat. 실행 계획 분석)
    Ant_U
    Ant_U

    티스토리툴바