Today I Learned
실행 계획에서 table 컬럼, type컬럼
SELECT NOW();
SELECT NOW() FROM DUAL;
두 쿼리 모두 같은 것.
FROM 없어도 쿼리는 실행이 되지만 일부 DBMS에서는 FROM이 필수인 곳이 있다.
그래서 MySQL은 호환성을 위해 DUAL이라는 스칼라 값이 있다.
결론은 FROM 없이 쿼리 실행할 때 FROM에 DUAL을 넣어도 되고 안넣어도 된다.
table 컬럼에서 <derived>
혹은 <union>
등 꺽새로 감싸인걸 을 볼 수 있다. 임시테이블을 의미한다.
예를 들면 이런거.
select dttm from (select now() as dttm) derived_table;
FROM에 있는건 SELECT문이지만 결과테이블에 안나온다.
(참고로 파생테이블에서는 별칭이 무조건 있어야한다)
type 컬럼
type 이후의 컬럼은 각 테이블의 레코드를 어떤 방식으로 읽는지 의미한다.
인덱스를 사용했는지 풀스캔인지 말이다.
쿼리튜닝시 인덱스를 효율적으로 사용하는지 확인하는 것이 중요하기때문에 실행계획에서 type컬럼은 반드시 체크해야한다.
system |
const |
eq_ref |
ref |
fulltext |
ref_or_null |
unique_subquery |
index_subquery |
range |
index_merge |
index |
ALL |
각 접근방식은 위에서부터 차례대로 빠르다.
ALL을 제외한 나머지는 모두 인덱스를 사용한 접근 방법.
하나의 단위 SELECT 쿼리는 위 접근방법중 단 하나만 사용가능.
index_merge를 제외한 나머지 접근방법은 반드시 하나의 인덱스만 사용.
MySQL 옵티마이저는 이런 접근 방식과 비용을 함께 계산해서 최소의 비용이 필요한 접근방식을 선택한다.
레코드가 1건만 존재하는 테이블이거나 한건도 존재하지않는 테이블을 참조하는 형태의 접근방법.
다른 DBMS에서는 UNIQUE INDEX SCAN이라고 한다.
반드시 1개의 레코드를 반환한다.
테이블의 레코드 건수와 관계없이 쿼리가 PK나 UNIQUE KEY 컬럼을 이용하는 WHERE 절을 가지고 있다.
예시
SELECT * FROM employees WHERE emp_no = 10001;
type컬럼이 const이면 옵티마이저가 쿼리를 최적화하는 단계에서 모두 상수화한다. 상수(const)인 것이다.
요약: 반드시 1건의 레코드만 반환
eq_ref는 여러 테이블이 조인되는 쿼리의 실행계획에서 표시된다.
예제
EXPLAIN
SELECT * FROM dept_emp de, employees e
WHERE e.emp_no = de.emp_no AND de.dept_no = 'd005';
id가 둘다 1로 같으므로 조인이 되었다는 것을 알수 있다.
FROM 절에서 dept_emp de 테이블이 실행계획 위쪽에 있으므로 dept_em 테이블을 먼저 읽는다.
그담으로 e.emp_no = de.emp_no
을 통해 employees e 테이블을 검색하고 있다.
이때 employees e 테이블의 emp_no이 PK라서 type칼럼이 eq_ref가 표시된다.
참고로 eq_ref는 여러테이블이 조인된 상태에서 두번째로 읽히는 테이블부터 나타난다.
요약: eq_ref로 나타난 다시말해서, 두번쨰테이블은 반드시 1건의 레코드만 반환)
from에 두개가 동시에 나열됐다고 생각하면 안되고 순서대로 봐야하고 employees e가 조인했다고 봐야 이해가 감.
ref는 조인의 순서나 PK나 UNIQUE KEY와 관계없이 =
equal 조건으로 검색할때 사용되어진다.
요약: 1건의 레코드만 반환된다는 보장이 없어도 됨
인덱스 분포도가 나쁘지않다면 성능장 문제를 일으키지 않는 접근법이다.
쿼리 튜닝할때 이세가지 접근방법에 대해서는 크게 신경쓰지 않아도 된다 (285p)