GROUP BY 처리
GROUP BY, ORDER BY 은 스트리밍 처리가 불가능함
GROUP BY에 사용된 조건은 인덱스를 사용할 수 없기 때문에 HAVING 절을 튜닝 하려고 인덱스를 생성하거나 다른 방법을 써도 인덱스를 사용할 수 없음
인덱스 스캔 : 인덱스를 차례로 읽는 방법
루스 인덱스 스캔 : 인덱스를 건너뛰면서 읽는 방법
인덱스를 사용하지 못하는 쿼리에서 GROUP BY는 임시테이블 사용
인덱스 스캔을 이용한 GROUP BY(타이트 인덱스 스캔)
GROUP BY칼럼으로 인덱스가 있다면 인덱스를 차례로 읽으면서 그루핑을 수행하고 그 결과를 조인함
GROUP BY가 인덱스를 통해 처리되는 쿼리는 이미 정렬된 인덱스를 읽는 것이므로 쿼리 실행 시점에 추가적인 정렬 작업이나 내부 임시 테이블은 필요하지 않음
루스 인덱스 스캔을 이용하는 GROUP BY
루스 인덱스 스캔 방법은 단일 테이블에 대해 수행되는 GROUP BY 처리에만 사용 가능함
루스 인덱스 스캔에서는 인덱스의 유니크한 값의 수가 적을수록 성능이 향상됨
루스 인덱스 스캔을 할 수 있는 쿼리들
루스 인덱스 스캔을 할 수 없는 쿼리들
임시 테이블을 사용하는 GROUP BY
GROUP BY의 기준 칼럼이 드라이빙 테이블에 있거나 드리븐 테이블에 있거나 상관없이 인덱스를 전혀 사용하지 못할 때 사용됨
GROUP BY가 필요한 경우 내부적으로 GROUP BY 절의 칼럼들로 구성된 유니크 인덱스를 가진 임시 테이블을 만들어서 중복 제거와 집함 함수 연산을 수행함
DISTINCT 처리
특정 칼럼의 유니크한 값만 조회 하려면 DISTINCT를 사용
집합함수가 없는 경우
MIN(), MAX(), COUNT() 같은 집합 함수와 함께 사용되는 경우
구분한 이유는 각 경우에 DISTINCT 키워드가 영향을 미치는 범위가 달라짐
DISTINCT 처리가 인덱스를 사용하지 못할 땐 임시 테이블을 사용
SELECT DISTINCT ...
SELECT 에서 유니크한 값을 가져오기 위해 DISTINCT를 사용하면 GROUP BY와 같은 방식으로 처리됨
DISTINCT는 SELECT 하는 레코드를 유니크하게 조회 하는것이지 특정 칼럼만 가져오는게 아님
SELECT DISTINCT first_name, last_name FROM employee;
first_name만 유니크한 값을 찾는게 아니라 (first_name, last_name) 조합이 유니크한 값을 찾는거임
SELECT DISTINCT(first_name), last_name FROM employee;
에러는 안나지만, DISTINCT는 함수가 아니라 ()를 사용하지 않고, ()는 제거하고 쿼리문이 실행되서 위 쿼리랑 같은 동작을 함
SELECT 절에 사용한 DISTINCT은 코든 칼럼에 영향을 미친다
?? 칼럼? 레코드가 아니라?
집합 항수와 함께 사용된 DISTINCT
집합 함수 내에서 사용된 DISTINCT는 그 집합 함수의 인자로 전달된 칼럼 값이 유니크한 것들을 가져옴
내부적으로는 COUNT(DISTINCT s.salary)를 처리하기 위해 임시테이블을 사용함
employee, salary 테이블을 조인한 결과에서 salary 칼럼의 값만 저장하기 위한 임시테이블을 만들어 사용함
COUNT(DISTINCT s.salary), COUNT(DISTINCT e.last_name)를 처리하기 위해 임시테이블을 2개를 사용함
인데스된 칼럼에 대해 DISTINCT 처리를 수행 하면 인덱스를 푸스캔하거나 레인지 스캔하면서 임시 테이블 없이 최적화된 처리가 가능함
내부 임시 테이블 활용
일반적으로 MySQL 엔진이 사용하는 임시 테이블은 처은에는 메모리에 생성됐다가 테이블의 크기가 커지면 디스크로 옮김
내부적인 임시테이블은 쿼리의 처리가 완료되면 자동 삭제됨
메모리 임시 테이블과 디스크 임시 테이블
MySQL 8.0부터 메모리는 TempTable이라는 스토리지 엔진을 사용하고, 디스트에 저장되는 임시 테이블은 InnoDB스토리지 엔진을 사용하도록 개선함
임시 테이블이 필요한 쿼리
MySQL 엔진에서 별도의 데이터 가공 작업을 필요로 하므로 대표적인 내부 임시 테이블으 생성하는 케이스
일반적으로 유니크 인덱스가 있는 내부 임시 테이블은 그렇지 않은 쿼리보다 처리 성능이 상당히 느림
임시테이블이 디스크에 생성되는 경우
내부 임시 테이블은 기본적으로 메모리 상에 만들어지지만, 메모리 임시 테이블을 사용할 수 없는 경우에는 디스크 기반의 임시테이블을 사용