기본 데이터 처리: DISTINCT 처리

공부하는 감자·2024년 3월 18일
0

MySQL

목록 보기
24/74
post-thumbnail

DISTINCT 처리

DISTINCT

  • 특정 칼럼의 유니크한 값만 조회하려면 SELECT 쿼리에 DISTINCT를 사용한다.
  • DISTINCT 키워드는 다음 경우에 영향을 미치는 범위가 달라진다.
    • MIN(), MAX(), COUNT() 같은 집합 함수와 함께 사용되는 경우
    • 집합 함수가 없는 경우
  • 집합 함수와 같이 DISTINCT가 사용되는 쿼리의 실행 계획에서 DISTINCT 처리가 인덱스를 사용하지 못할 때는 항상 임시 테이블이 필요하다.
    • 하지만 실행 계획의 Extra 칼럼에는 “Using temporary” 메시지가 출력되지 않는다.

SELECT DISTINCT …

  • 단순히 SELECT되는 레코드 중 유니크한 레코드만 가져오고자 할 때 SELECT DISTINCT 형태의 쿼리 문장을 사용한다.
    • DISTINCT는 SELECT하는 레코드(튜플)를 유니크하게 SELECT하는 것이지, 특정 칼럼을 유니크하게 조회하는 것이 아니다.
  • GROUP BY와 동일한 방식으로 처리된다.
  • MySQL 8.0 버전부터 GROUP BY를 수행하는 쿼리에 ORDER BY 절이 없으면 정렬을 사용하지 않기 때문에, 다음 두 쿼리는 내부적으로 같은 작업을 수행한다.
    SELECT DISTINCT emp_no FROM salaries;
    SELECT emp_no FROM salaries GROUP BY emp_no;

집합 함수와 함께 사용된 DISTINCT

  • COUNT(), MIN(), MAX() 같은 집합 함수 내에서 DISTINCT가 사용될 경우, 그 집합 함수의 인자로 전달된 칼럼 값이 유니크한 것들을 가져온다.
    SELECT COUNT(DISTINCT s.salary)
    FROM employees e, salaries s
    WHERE e.emp_no = s.emp_no
    AND e.emp_no BETWEEN 100001 AND 100100;
    • 위 쿼리는 두 테이블을 조인한 결과에서 salary 칼럼의 값만 저장하기 위한 임시 테이블을 만들어서 사용한다.
    • 임시 테이블의 salary 칼럼에는 유니크 인덱스가 생성되기 때문에 레코드 건수가 많아진다면 상당히 느려질 수 있는 형태의 쿼리다.
    • 쿼리에 COUNT(DISTINCT e.last_name) 를 하나 더 추가한다면, 실행 계획은 똑같이 표시되지만 salary 칼럼의 값을 저장하는 임시 테이블과 last_name 칼럼의 값을 저장하는 임시 테이블이 필요하므로 전체적으로 2개의 임시 테이블을 사용한다.
  • 내부적으로 임시 테이블을 사용하지만 쿼리의 실행 계획에는 임시 테이블을 사용한다는 메시지는 표시되지 않는다.
    • 모든 버전의 MySQL 서버에서 실행 계획에 “Using temporary”를 표시하지 않고 있다.
  • 인덱스된 칼럼에 대해 DISTINCT 처리를 수행할 때는 인덱스를 풀 스캔하거나 레인지 스캔하면서 임시 테이블 없이 최적화된 처리를 수행할 수 있다.
    SELECT COUNT(DISTINCT emp_no) FROM employees;
    SELECT COUNT(DISTINCT emp_no) FROM dept_emp GROUP BY dept_no;

Reference

참고 서적

📔 Real MySQL 8.0

profile
책을 읽거나 강의를 들으며 공부한 내용을 정리합니다. 가끔 개발하는데 있었던 이슈도 올립니다.

0개의 댓글