SELECT *
FROM employees e
INNER JOIN salaries s ON s.emp_no=e.emp_no
WHERE e.first_name='Matt'
AND e.hire_Date BETWEEN '1995-11-21' AND 1986-11-21';
| id | table | type | key | rows | filtered | Extra |
|---|---|---|---|---|---|---|
| 1 | e | ref | ix_firstname | 233 | 100.00 | Using where |
| 1 | s | ref | PRIMARY | 10 | 100.00 | NULL |
employees 테이블에서 ix_firstname 인덱스로 조건에 맞는 233건 레코드를 검색hire_date 조건에 맞는 레코드를 필터링하는데 이 실행 계획에서는 filered 칼럼이 100인 것으로 보아 233건 모두 만족할 것으로 예측했다.salaries 테이블의 프라이머리 키를 이용해 slalaries 테이블의 레코드를 읽는데 옵티마이저는 employees 테이블 레코드 한 건당 salaries 테이블 레코드 10건이 일치할 것으로 예상했다.| id | table | type | key | rows | filtered | Extra |
|---|---|---|---|---|---|---|
| 1 | e | ref | ix_firstname | 233 | 23.20 | Using where |
| 1 | s | ref | PRIMARY | 10 | 100.00 | NULL |
first_name으로 거른 결과인 233건에서 hire_date 조건까지 만족하는 값은 233건에서 23%라고 예측한 것condition_fanout_filter를 활성화하면 인덱스를 사용할 수 없는 조건에 대해서도 얼마나 조건을 충족할지를 고려하게 된다.
FROM절에 서브 쿼리가 있으면 먼저 실행해서 임시 테이블로 만든 다음 외부 쿼리를 처리했다.SELECT * FROM (
SELECT * FROM employees WHERE first_name='Matt'
) derived_table
WHERE derived_table.hire_date='1996-04-03';
| id | select_type | table | type | key |
|---|---|---|---|---|
| 1 | PRIMARY | ref | ||
| 2 | DERIVED | employees | ref | ix_firstname |
employees 테이블을 읽는 select_type이 DERIVED인 것을 보아 조건에 맞는 임시 테이블을 생성했다고 볼 수 있다.
derived_merge 옵션을 활성화하면 실행 계획이 아래와 같이 변한다.| id | select_type | table | type | key |
|---|---|---|---|---|
| 1 | SIMPLE | employees | index_merge | ix_hiredate, ix_firstname |
DISTINCT가 사용된 서브 쿼리GROUP BY나 HAVING이 사용된 서브 쿼리LIMIT가 사용된 서브 쿼리UNION 또는 UNION ALL을 포함하는 서브 쿼리SELECT 절에 사용된 서브 쿼리