쿼리에 ORDER BY를 사용하면 다음의 3가지 처리 방식중 하나로 정렬된다.
인덱스 정렬 처리 방식 | explain Extra |
---|---|
인덱스 정렬 | 표시내용없음 |
드라이빙 테이블만 정렬 | USing filesort |
임시테이블에서 정렬 | Using temporary; Using filesort |
ORDER BY에 명시된 컬럼이 제일 먼저 읽은 테이블(드라이빙)에 속하고 ORDER BY 순서대로 생성된 인덱스가 있어야 한다. 또한 WHERE절에 첫 번째 읽은 테이블의 컬럼에 대한 조건이 있다면 그 조건과 ORDER BY는 같은 인덱스를 사용할 수 있어야한다. 그리고 B-TREE
계열 인덱스만 정렬을 사용할 수 있다.
그 이유는 B-TREE
는 인덱스가 키값으로 정렬돼 있기 때문에 순서대로 읽기만 하면 되기때문이다.
조인을 실행하기 전에 첫 번째 테이블의 레코드를 먼저 정렬한 뒤 조인을 실행하는 것이 모든 레코드를 정렬하는 것보다 더 효율 적이다.
SELECT * FROM employees e, salaries s
WHERE s.emp_no = e.emp_no
AND e.emp_no BETWEEN 10001 AND 10010
ORDER BY e.last_name
위 쿼리의 ORDER BY 절에 명시된 컬럼은 employees 테이블의 primary key 와 연관이 없으므로 인덱스를 사용한 정렬은 불가능하다. 하지만, e.last_name
에 포함된 컬럼이므로 옵티마이저는 employees
(드라이빙) 테이블만 먼저 정렬 하고 그결과와 salaries 테이블과 조인을 수행한다.
임시 테이블을 이용한 정렬은 위의 정렬처리 방식중 가장 느린 방식이다.
SELECT * FROM employees e, salaries s
WHERE s.emp_no = e.emp_no AND e.emp_no BETWEEN 100002 AND 100010
ORDER BY s.salary
위의 쿼리는 employees 테이블이 드라이빙 테이블이지만 salaries 드리븐 테이블의 컬럼을 사용하여 정렬을 수행하였다. 정렬이 수행되기 전에 salaries 테이블을 읽어야 하므로 이 쿼리는 반드시 조인된 데이터를 가지고 정렬할 수 밖에 없다.
일반적으로는 조인이 수행이 되면 레코드 건수는 거의 배수로 늘어나기 때문에 가능하다면 드라이빙 테이블을 정렬한 다음 조인을 수행하는 방법이 효율적이다.