320x100
320x100

실행 계획

: 쿼리를 실행하기 전에 쿼리의 범위와 검색 방법 등을 미리 확인하는 것

 

- 쿼리

EXPLAIN <실행할 쿼리>

 

- 확인가능한 항목

: id

: select_type

: table

: type

: possible_keys

: key

: key_len

: ref

: rows

: extra

 

 

 

 

 

 

id

: SELECT 쿼리별 부여되는 식별자 값

: 여러 개의 테이블을 JOIN하면 JOIN되는 테이블의 개수만큼 실행계획 레코드가 출력되지만 id는 동일

 

 

 

 

 

select_type

: SELECT 쿼리가 어떤 타입의 쿼리인지 표시

 

- SIMPLE

: UNION이나 서브 쿼리를 사용하지 않는 단순한 SELECT 쿼리

 

- PRIMARY

: UNION이나 서브 쿼리가 포함된 SELECT 쿼리에서 실행 계획의 가장 바깥쪽의 단위 쿼리

 

- UNION

: UNION으로 결합되는 단위의 SELECT 쿼리에서 두 번째 이후의 SELECT 쿼리

 

- DEPENDENT UNION

: UNION이나 UNION ALL로 집합을 결합하는 쿼리에 표시

: 결합된 단위 쿼리가 외부의 영향을 받는 것을 의미

 

- UNION RESULT

: UNION 결과를 담아두는 테이블

 

- SUBQUERY

: FROM 절 이외에서 사용되는 서브 쿼리

: Nested Query (중첩된 쿼리. SELECT 되는 컬럼에 사용된 서브 쿼리)

: Sub Query (WHERE 절에 사용된 서브 쿼리)

: Dericed (파생 테이블. FROM절에 사용된 서브 쿼리)

 

- DEPENDENT SUBQUERY

: 바깥쪽 SELECT 쿼리에서 정의된 컬럼을 사용하는 서브 쿼리

 

- DRIVED

: 서브쿼리가 FROM 절에 사용된 경우 만들어지는 실행 계획

: 임시 테이블에서 파생된 테이블

: 해당 경우에는 JOIN을 사용하는 것을 권장

 

- UNCACHEABLE SUBQUERY

: 캐시가 불가능한 서브 쿼리

 

- UNCACHABLE UNION

: UNION 요소 중 특정 요소로 인해 캐시가 불가능한 경우

 

 

 

 

 

 

 

table

: MySQL의 실행 계획은 테이블 기준으로 표시됨

: 테이블 이름에 별칭이 부여된 경우 별칭이 표시됨

: <>으로 감싸져 있는 경우 임시 테이블을 지칭

: <>안에 표시되는 수자는 단위 SELECT id를 지칭

 

 

 

 

 

type

: MySQL 서버가 각 테이블의 레코드를 어떤 방식으로 읽었는지 의미

: 인덱스를 사용했는지, Full scan을 사용했는지 등

 

- system

: 레코드가 1건만 존재하는 테이블 또는 한건도 존재하지 않는 테이블을 참조하는 형태의 접근

: InnoDB 테이블에서는 나타나지 않음

 

- const

: 테이블 레코드 건수에 상관없이 쿼리가 PRIMARY KEY나 UNIQUE KEY 컬럼을 이용하는 WHERE 조건을 가지고

  있으면서 반드시 1건을 반환하는 쿼리

 

- eq_ref

: 여러 테이블이 조인되는 쿼리의 실행 계획에서 표시

: 조인에서 처음이 읽은 테이블의 컬럼 값을 그 다음 읽어야할 테이블의 PK 컬럼의 검색 조건에 사용할 때

: 조인에서 두번째 이후에 읽은 테이블에서 레코드가 1건만 존재한다는 보장이 있어야 사용되는 접근 방법

 

- ref

: 인덱스 종류와 상관없이 동등 조건으로 검색 될 때

: 반환되는 레코드가 1건이 아닐 수 있으므로 const나 ep_ref에 비해 느림

 

- fulltext

: MySQL의 전문검색(Fulltext) 인덱스를 사용해 레코드를 읽는 접근 방법

 

- ref_of_null

: ref에서 NULL 비교가 추가된 형태

 

- unique_subquery

: WHERE 조건에서 사용될 수 있는 IN 형태의 쿼리를 위한 접근 방법

: 서브 쿼리에서 중복되지 않은 UNQUE한 값만 반환하는 경우

 

- index_subquery

: IN에서 서브 쿼리가 중복된 값을 반환할 수 있지만 중복된 값을 인덱스를 이용해 제거할 수 있을 때

 

- range

: index range scan 방법

: < 이나 >, IS NULL, BETWEEN, IN, LIKE 등 연산자 이용 시 나옴

: 어느 정도의 성능 보장 가능

 

- index_merge

: 2개 이상의 인덱스를 이용해 각각의 검색 결과를 만들어낸 후 결과를 병합하는 처리 방식

 

- index

: 인덱스에 대해 full scan을 하는 처리

 

- ALL

: 테이블에 대한 full scan을 하는 처리. 가장 비효율적인 방법

 

 

 

 

 

 

 

possible_keys

: MySQL OPTIMIZER가 최적의 실행 계획을 만들기 위해 후보로 선정했던 접근 방식에서 사용된 인덱스 목록

 

 

 

 

 

key

: 최종 선택된 실행 계획에서 사용하는 인덱스

 

 

 

 

 

key_len

: 쿼리를 처리하기 위해 다중 컬럼으로 구성된 인덱스에서 몇개의 컬럼까지 사용했는지 알려주는 값

: 인덱스의 각 레코드에서 몇 바이트까지 사용했는지 의미

 

 

 

 

 

ref

: 접근 방법이 ref면 참조 조건으로 어떤 값이 제공되었는지 의미

: 상수값이라면 const, 다른 테이블의 컬럼 값이라면 테이블명과 컬럼명을 표시

: 값 자체의 연산을 거친 경우 func 

 

 

 

 

 

rows

: 실행계획의 효율성 판단을 위해 예측했던 레코드 건수

: 스토리지 엔진별로 갖고 있는 통계정보를 참조하여 OPTIMIZER가 산출해낸 예상 값

: 쿼리를 처리하기 위해 얼마나 많은 레코드를 읽고 체크해야하는지 의미

: LIMIT이 포함되는 쿼리가 반영되지 않아 부정확함

 

 

 

 

 

extra

: 쿼리 실행계횎에서 성능에 관련된 중요한 내용

 

- const row not found

: type 컬럼이 const인데 해당 테이블에 레코드가 1건도 없는 경우

 

- Distinct

: DINSTINCT를 처리하기 위해 꼭 필요한 항목만 조인했다는 의미

 

- Full scan in NULL key

: 컬럼의 값 중 NULL이 있으면 테이블을 full scan 하겠다는 의미

 

- Impossible HAVING

: 쿼리에 HAVING 절의 조건을 만족하는 레코드가 없는 경우

 

- Impossible WHERE

: 테이블 구조상 WHERE가 FALSE가 될 수 밖에 없음

 

- Impossible WHERE noticed after reading const table

: WHERE 조건에 일치하는 데이터가 없는 경우

 

- No matching min/max row

: MAX(), MIN()과 같은 집합 함수가 있는 쿼리의 조건절에 일치하는 레코드가 없는 경우

 

- no matching row in const table

: 조인에 사용된 테이블에서 const 방식으로 접근할 때 일치하는 레코드가 없는 경우

 

- No tables used

: FROM 절이 없는 쿼리 문장 실행 시

 

- Not exists

: NOT IN과 NOT EXISTS와 같은 안티 조인을 사용한 경우

: 레코드가 많을 경우 OUTER JOIN을 사용하는 것을 권장

 

- Range checked for each record

: 모든 레코드 마다 insex range scan을 체크할 때

 

- scanned N databases

: 쿼리를 통해 INFORMATION_SCHEMA DB에서 메타정보를 검색하는 경우

 

- Select tables optimized away

: MAX() 또는 MIN()만 SELECT 절에 사용되거나 GROUP BY에 사용되는 경우

  쿼리가 적절한 인덱스를 사용할 수 없을 때 인덱스를 오름차순 혹은 내림차순으로 1건만 읽는 형태의 최적화가

  적용되는 경우

 

- unqique row not found

: 두 개의 테이블이 각각 유니크 컬럼으로 OUTER 조인을 수행하는 쿼리에서 OUTER 테이블에 일치하는

  레코드가 존재하지 않을 때

 

- Using filesort

: ORDER BY를 처리하기 위해 적절한 인덱스를 사용하지 못하는 경우

 

- Using index

: 데이터 파일을 전혀 읽지 않고 인덱스만 읽어서 쿼리를 모두 처리할 수 있는 경우

 

- Using index for group-by

: GROUP BY 처리가 인덱스를 이용하는 경우

 

- Using join buffer

: 읽은 레코드를 조인 버퍼에 저장하는 경우

 

- Ussing intersect

:  각각의 인덱스를 사용할 수 있는 조건이 AND로 연결된 경우 각 처리결과에서 교집합 추출

 

- Using union

: 각 인덱스를 사용할 수 있는 조건이 OR로 연결된 경우 각 처리 결과에서 합집합 추출

 

- Using sort_union

: 대량의 range들이 OR로 연결되어 있는 경우 WHERE 조건에 사용된 비교 조건이 모두 동등 조건이 아닐 때

 

- Using temporaty

: 쿼리를 처리하는 동안 중간 결과를 담아두기 위해 임시 테이블을 사용하는 경우

 

- Using where

: 스토리지 엔진에서 전달받은 데이터를 MySQL 엔진레이어에서 체크 조건으로 필터링 하는 경우

: 가장 흔하게 표시되는 키워드

 

 

 

 

 

 

Refference

 

[MySQL]MySQL 벼락치기(7) - 실행계획(1)

이번 포스팅은 사내에서 MySQL 관련 내용 발표를 위해 Real MySQL(http://wikibook.co.kr/real-mysql/) 서적을 기반으로 학습하고 이해한 내용을 정리하는 포스팅이다. 포스팅에서는 주로 InnoDB 스토리지 엔진

idea-sketch.tistory.com

300x250
728x90