select_type
칼럼에 표시될 수 있는 값은 다음과 같다.UNION
이나 서브쿼리를 사용하지 않는 단순한 SELECT 쿼리인 경우 표시되는 값이다.select_type
이 SIMPLE
인 단위 쿼리는 하나만 존재한다.select_type
이 SIMPLE
로 표시된다.UNION
이나 서브쿼리를 가지는 SELECT 쿼리의 실행 계획에서 가장 바깥쪽(Outer)에 있는 단위 쿼리인 경우이다.PRIMARY
로 표시되며, 단 하나만 존재한다.UNION
으로 결합하는 단위 SELECT 쿼리 가운데 첫 번째를 제외한 두 번째 이후 단위 SELECT 쿼리는 이 값으로 표시된다.UNION
의 첫 번째 단위 SELECT의 select_type
은 UNION
되는 쿼리 결과들을 모아서 저장하는임시 테이블(DERIVED
)로 표시된다.UNION select_type
과 마찬가지로, UNION
이나 UNION ALL
로 집합을 결합하는 쿼리에서 표시된다.DEPENDENT
는 UNION
이나 UNION ALL
로 결합된 단위 쿼리가 외부 쿼리에 의해 영향을 받는 것을 의미한다.외부의 employees(e1) 테이블을 먼저 읽은 다음 서브 쿼리를 실행한다.
이때 employees 테이블의 칼럼값이 서브쿼리에 영향을 준다. (내부 쿼리가 외부의 값을 참조해서 처리된다)
EXPLAIN
SELECT *
FROM employees e1 WHERE e1.emp_no IN (
## 내부적으로 WHERE 조건에 e2.emp_no=e1.emp_no라는 조건이 자동으로 추가된다.
SELECT e2.emp_no FROM employees e2 WHERE e2.first_name='Matt'
UNION
## 내부적으로 WHERE 조건에 e3.emp_no=e1.emp_no라는 조건이 자동으로 추가된다.
SELECT e3.emp_no FROM employees e3 WHERE e3.last_name='Matt'
);
UNION
결과를 담아두는 테이블을 의미한다.UNION ALL
이나 UNION(또는 UNION DISTINCT)
쿼리는 모두 UNION의 결과를 임시 테이블로 생성했다.UNION ALL
의 경우 임시 테이블을 사용하지 않도록 기능이 개선되었으나, **UNION(또는 UNION DISTINCT)
쿼리는 여전히 임시 테이블에 결과를 버퍼링**한다.select_type
이 UNION RESULT
로 표시된다.UNION RESULT
는 실제 쿼리에서 단위 쿼리가 아니기 때문에 별도의 id 값은 부여되지 않는다.UNION RESULT
의 table
칼럼은 <union n,m>
으로 표시된다.UNION
했다는 의미이다.DEPENDENT
라는 키워드가 붙는다.EXPLAIN
SELECT e.first_name,
(SELECT COUNT(*)
FROM dept_emp de, dept_manager dm
WHERE dm.dept_no=de.dept_no AND de.emp_no=e.emp_no) AS cnt
FROM employees e
WHERE e.first_name='Matt';
DEPENDENT
키워드가 없는 일반 서브쿼리보다는 처리 속도가 느릴 때가 많다.DERIVED
는 단위 SELECT 쿼리의 실행 결과로 메모리나 디스크에 임시 테이블을 생성하는 것을 의미한다.select_type
이 DERIVED
인 경우에 생성되는 임시 테이블을 “파생 테이블”이라고도 한다.DERIVED
와 같은 의미로 이해하면 된다.select_type
이 DERIVED
인 실행 계획을 만든다.optimizer_switch
시스템 변수)에 따라 FROM 절의 서브쿼리를 외부 쿼리와 통합되는 형태의 최적화가 수행되기도 한다.DERIVED
형태의 실행 계획을 조인으로 해결할 수 있게 쿼리를 바꿔주는 것이 좋다.LATERAL JOIN
기능이 추가되면서 FROM 절의 서브쿼리에서도 외부 칼럼을 참조할 수 있게 되었다.이전 버전까지는 FROM 절의 서브쿼리는 외부 칼럼을 사용할 수 없었다.
## LATERAL JOIN의 가장 대표적인 활용 예제
SELECT *
FROM employees e
LEFT JOIN LATERAL
(SELECT *
FROM salaries s
WHERE s.emp_no=e.emp_no
ORDER BY s.from_date DESC LIMIT 2) AS s2 ON s2.emp_no=e.emp_no;
LATERAL
키워드가 없는 서브쿼리에서 외부 칼럼을 참조하면 오류가 발생한다.select_type
칼럼의 DEPENDENCY DERIVED
키워드는 해당 테이블이 래터럴 조인으로 사용된 것을 의미한다.SUBQUERY
와 DEPENDENT SUBQUERY
는 다음과 같이 캐시를 사용한다.SUBQUERY
는 바깥쪽(Outer)의 영향을 받지 않으므로 처음 한 번만 실행해서 그 결과를 캐시하고 필요할 때 캐시된 결과를 이용한다.DEPENDENT SUBQUERY
는 의존하는 바깥쪽(Outer) 쿼리의 칼럼의 각 단위로 캐시해두고 사용한다. → 외부(Outer) 쿼리의 값 단위로 캐시가 만들어진다.select_type
이 UNCACHEABLE SUBQUERY
로 표시된다.사용자 변수가 서브쿼리에 사용된 경우
NOT-DETERMINISTIC 속성의 스토어드 루틴이 서브쿼리 내에 사용된 경우
UUID()나 RAND()와 같이 결과값이 호출할 때마다 달라지는 함수가 서브쿼리에 사용된 경우
## 사용자 변수(@status)가 사용된 쿼리 예제
SELECT *
FROM employees e
WHERE e.emp_no = (
SELECT @status FROM dept_emp de WHERE de.dept_no='d005';
);
UNION
과 UNCACHEABLE
키워드의 속성이 혼합된 select_type
을 의미한다.UNION
에서 결과를 캐시할 수 없는 경우에 이 칼럼이 표시되는 듯하다.select_type
이다.EXPLAIN
SELECT *
FROM employees e
WHERE e.emp_no IN (
SELECT emp_no FROM salaries WHERE salary BETWEEN 100 AND 1000
);
select_type
의 MATERIALIZED
키워드로 알 수 있다.