MySQL 실행계획 분석
학습자료 : 업무에 바로 쓰는 SQL 튜닝, 양바른 저
쿼리의 실행계획을 보기 위한 명령어 키워드
EXPALIN 쿼리;
DESCRIBE 쿼리;
DESC 쿼리;
실행계획 조회시 의미하는 정보들
1. id
실행 순서를 표시하는 숫자(순서가 낮을 수록 먼저 실행되었음을 의미)
조인 또는 서브쿼리를 사용하였을 때, 순서를 확인할 수 있음
조인되었다면, 같은 순서로 표시함
2. select_type
select 쿼리의 유형을 표시함
SIMPLE
union 또는 내부 쿼리가 없는 경우를 표시함
단순 select 쿼리
PRIMARY
서브쿼리를 감싸는 외부쿼리
union이 포함된 쿼리에서 첫 번째로 select를 사용한 쿼리
SUBQUERY
독립적으로 수행된 서브쿼리를 표시
select 절의 스칼라 서브쿼리와 where절의 중첩 서브쿼리
DERIVED
from 절에 작성된 서브쿼리를 의미
별도의 임시 테이블인 인라인 뷰
UNION
UNION 또는 UNION ALL 구문으로 합쳐진 select 문에서 첫번째 select 이외의 select문
UNION RESULT
UNION ALL이 아닌 UNION 구문으로 SELECT 절을 결합했을 때, 표시함
UNION의 경우, 임시 테이블을 생성하여 메모리에서 정렬하여 중복체크하는 과정을 거침
UNION RESULT는 이러한 과정을 진행했다는 것으로 해석할 수 있음
데이터의 유일성을 보장할 수 있다면, UNION ALL로 쿼리를 튜닝하는 편이 성능적으로 유리함
DEPENDENT SUBQUERY
UNION 또는 UNION ALL을 사용하는 서브쿼리가 메인 테이블의 영향을 받는 경우에, UNION으로 연결된 쿼리 중에 첫 번째 단위 쿼리를 의미함
단위 쿼리가 메인 테이블로부터 값을 하나씩 공급 받아야하는 구조이기에, 쿼리 튜닝 대상이 됨
DEPENDENT UNION
DEPENDENT SUBQUERY와 같이 첫 번째 단위쿼리가 아닌 두 번째 단위쿼리를 의미함
쿼리 튜닝 대상
UNCACHEABLE SUBQUERY
메모리에서 캐싱되어 재활용되어야 할 서브쿼리가 재사용되지 못함을 의미함
서브쿼리 내부에 사용자 정의함수나 사용자 변수가 포함된 경우
RAND(), UUID() 함수 등을 통해서 매번 조회시마다 결과가 달라지는 경우
서브쿼리의 결과가 메모리에 상주할 수 있도록, 튜닝을 고려해보는 것이 좋음
MATERIALIZED
IN 절 구문에 연결된 서브쿼리가 임시 테이블을 생성한 뒤, 조인이나 가공작업을 수행할 때 표시함
3. table
테이블명을 표시하는 항목
테이블명 혹은 테이블 별칭(alias)
서브쿼리나 임시테이블 생성의 경우
<subquery#>, <derived#> 으로 표시함(#의 경우 id를 표시)
4. partitions
데이터가 저장된 논리적인 영역을 표시하는 항목
파티션이 나눠져있다면, 특정 파티션에서만 데이터를 조회하는 것이 성능적으로 유리함
5. type
테이블의 데이터를 어떻게 찾을지에 관한 정보를 제공하는 항목
system
테이블에 데이터가 없거나, 하나만 있는 경우
최고의 성능
const
조회되는 데이터가 단 1건 출력되는 유형
고유 인덱스 또는 기본 키를 사용하여 1건만 조회
eq_ref
조인이 수행될 때, 드리븐 테이블의 데이터에 접근할 때, 고유 인덱스 또는 기본키로 1건의 데이터만 조회하는 유형
조인이 수행될 때, 성능상 가장 좋음
ref
eq_ref와 흡사하지만, 드리븐 테이블의 데이터 접근 범위가 2개 이상인 경우를 의미함
드리븐 테이블의 데이터가 많을 경우, 성능 저하의 원인이 되는지 파악할 필요가 있음
=,>,<등의 연산자를 사용해서 인덱스로 생성된 열을 비교하는 경우 또한 의미함
ref_or_null
ref 유형과 흡사하지만 IS NULL 구문에 대해서 인덱스를 활용화도록 최적화된 방식
NULL에 대해서도 인덱스를 활용할 수 있음, 이 때 NULL이 가장 앞쪽에 정렬되어 있음
NULL 데이터 양이 적다면, 효율적인 쿼리지만, NULL이 많다면 튜닝 대상이 될 수 있음
range
테이블 내의 연속된 데이터 범위를 조회하는 유형
=,<>,>,>=,<,<=, IS NULL,<=>, BETWEEN, IN 연산을 활용하는 경우범위가 넓으면 성능 저하의 원인이 될 수 있음
fulltext
텍스트 검색을 위해서 full text index를 활용하는 유형
index_merge
특정 테이블에 생성된 2개 이상의 인덱스가 병합되어 동시에 적용되는 경우
full text index는 제외
index
index를 전체 탐색하는 경우(full scan)
인덱스 또한 물리적인 영역으로 저장되어 있지만, table 보다는 크기가 작기 때문에 table full scan보다는 유리함
ALL
table full scan
인덱스가 없거나, 옵티마이저가 인덱스를 활용하는 것이 더 비효율적이라고 판단했을 경우에 해당함
전체 테이블의 10~20% 이상의 데이터를 조회할 경우 full scan이 성능상 유리할 수 있음
6. possible_keys
옵티마이저가 쿼리를 최적화하고자 사용할 수 있는 인덱스 목록을 표시함
사용할 수 있는 기본 키와 인덱스 목록을 보여주는 것으로, 실제 사용하는 인덱스가 아님
7. key
쿼리를 최적화하고자 사용한 기본 키 또는 인덱스명을 의미함
어떤 인덱스를 활용했는지 확인할 수 있어서, 비효율적인 인덱스 혹은 인덱스를 사용하지 않았다면 튜닝의 대상이 됨
8. key_len
인덱스를 사용할 때, 인덱스 전체 혹은 일부를 사용하게 됨
사용한 인덱스의 바이트 수를 의미함
INT 4바이트, VARCHAR 3바이트 / UTF-8기준
9. ref
reference의 약자로 테이블 조인을 수행할 때 어떤 조건으로 해당 테이블에 엑세스 되었는지를 보여줌
10. rows
쿼리를 수행하고자 접근하는 데이터의 모든 행의 수를 나타내는 예측 항목을 의미
메모리에서 처리해야 할 행 수를 예상하는 값으로 수치가 정확하진 않고, 최종 출력될 행 수가 아님
최종 결과 건수와 비교해 차이가 많다면, 튜닝의 대상이 될 수 있음
11. filtered
DB 엔진으로 가져온 데이터 대상으로 필터 조건에 따라 어느 정도의 비율로 데이터를 제거했는지를 의미하는 항목
단위는 %
12. extra
SQL문을 어떻게 수행할 것인지에 관한 추가 정보를 보여주는 항목,
;으로 구분30여 가지 항목으로 정리할 수 있음
MySQL에서는 extra에서 수행되는 정보가 모두 출력되지 않음
Distinct
중복이 제거되어 유일값을 찾을 때
distinct 키워드 혹은 union 구문 활용
Using where
where 절의 필터 조건을 사용해서 MySQL 엔진으로 가져온 데이터를 추출할 것을 의미
Using temporary
테이블의 중간 결과를 저장하고자 임시 테이블을 생성하겠다는 의미
데이터를 가져와 정렬 작업을 수행하거나 중복을 제거하는 작업 등을 수행
DISTINCT, GROUP BY, ORDER BY 구문이 포함된 경우 표시됨
튜닝의 대상이 될 수 있음
Using index
물리적인 데이터 파일을 읽지 않고 인덱스만을 읽는 경우
커버링 인덱스
Using filesort
정렬이 필요한 데이터를 메모리에 올리고 정렬 작업을 수행한다는 의미함
정렬을 위해서 메모리 영역에 데이터를 올리기 때문에 튜닝 검토 대상이 될 수 있음
Using join buffer
조인을 수행하기 위해 중간 데이터 결과를 저장하는 조인 버퍼를 사용한다는 의미
드라이빙 테이블의 데이터에 먼저 접근한 결과를 조인 버퍼에 담고, 조인 버퍼와 드린 테이블 간에 서로 일치하는 조인 키값을 찾는 과정을 수행하는 경우
Using union/Using intersect/ Using sort_union
type이 index_merge일 때, 인덱스를 어떻게 병합했는지 표시함
Using union의 경우 합집합, OR 구문
Using intersect의 경우 교집합, AND 구문
Using sort_union의 경우, WHERE 절의 OR 구문이 동등조건이 아닐 때
Using index condition
using where과 달리 필터 조건을 스토리지 엔진으로 전달하여, MySQL 엔진의 부하를 줄이는 방식
Using index condition(BKA)
Using index condition과 흡사하지만, 데이터 검색을 위해 배치 키 엑세스를 사용하는 방식
Using index for group-by
SQL 문에 GROUP BY 또는 DISTINCT 구문이 포함 될 때, 인덱스로 정렬 작업을 수행하여 최적화함
인덱스 루스 스캔일 때, 표시함
Not exists
하나의 일치하는 행을 찾으면 추가로 행을 더 검새학지 않아도 될 때 표시함
left outer join, right outer join의 경우 테이블에 존재하지 않는 데이터를 명시적으로 검색할 때 발생함
MySQL의 학장된 실행 계획 수행
EXPLAIN FORMAT = TRADITIONAL
기본
EXPLAIN ANALYZE
실제 측정한 실행 계획 정보를 출력
MySQL 8.0.18 이상 버전부터 SELECT 문 대상으로 수행 가능
Last updated