8.8.2 EXPLAIN 출력 포맷
EXPLAIN
문은 SELECT
문의 실행 계획에 대한 정보를 제공합니다.
EXPLAIN
은 SELECT
문에서 사용되는 각 테이블에 대한 정보 행을 반환합니다. 이것은 MySQL이 문을 처리하는 동안 테이블을 읽는 순서대로 출력에 테이블을 나열합니다. MySQL은 Nested Loop Join 메소드를 사용하여 모든 결합을 해결합니다. 이것은 MySQL이 첫 번째 테이블에서 행을 읽고 다음 두 번째 테이블, 세 번째 테이블과 같이, 일치하는 행을 찾는 것을 의미합니다. 모든 테이블이 처리되면, MySQL은 선택된 컬럼을 출력하고, 일치하는 행이있는 테이블을 찾을 때까지 테이블 목록 퇴보합니다. 다음 행을 테이블에서 읽은 프로세스는 다음 테이블로 이동합니다.
EXTENDED
키워드를 사용하면 EXPLAIN
은 EXPLAIN
문에 계속 SHOW WARNINGS
명령문을 발행하여 표시 할 수있는 추가 정보를 생성합니다. EXPLAIN EXTENDED
는 필터 처리된 칼럼
도 표시합니다. 섹션 8.8.3 "EXPLAIN EXTENDED 출력 형식" 을 참조하십시오.
EXTENDED
키워드와 PARTITIONS
키워드를 동일한 EXPLAIN
문을 함께 사용 할 수 없습니다.
EXPLAIN
출력 컬럼EXPLAIN
결합 형EXPLAIN
추가 정보EXPLAIN
출력의 해석
EXPLAIN 출력 컬럼
이 섹션에서는 EXPLAIN
에 의해 생성되는 출력 컬럼에 대해 설명합니다. 뒤의 섹션에서 type
과 Extra
컬럼에 대한 추가 정보를 제공합니다.
EXPLAIN
의 각 출력 행은 하나의 테이블에 대한 정보를 제공합니다. 각 행은 표 8.1 "EXPLAIN 출력 열" 로 요약하고 다음 표에 설명되어있는 값이 포함됩니다.
표 8.1 EXPLAIN 출력 컬럼
컬럼 | 의미 |
---|---|
id | SELECT 식별자. |
select_type | SELECT 형 |
table | 출력 행의 테이블 |
partitions | 일치하는 파티션 |
type | 결합 형 |
possible_keys | 선택 가능한 인덱스 |
key | 실제로 선택된 인덱스 |
key_len | 선택된 키의 길이 |
ref | 인덱스와 비교되는 컬럼 |
rows | 조사되는 행의 견적 |
filtered | 테이블 조건에 의해 필터링되는 행의 비율 |
Extra | 추가 정보 |
id
SELECT
식별자. 이것은 쿼리의SELECT
의 연번입니다. 행이 다른 행의 합집합 결과를 참조하는 경우, 값은NULL
이 될 수 있습니다. 이 경우table
컬럼은<union
등의 값이 표시되고 행이M
,N
>M
과N
의id
값이있는 행의 합집합을 참조하는 것이 표시됩니다.select_type
SELECT
유형에서 다음 표에 나와 있지만 중 하나입니다.select_type
값의미 SIMPLE
간단한 SELECT
(UNION
이나 서브 쿼리를 사용하지 않습니다)PRIMARY
가장 바깥 쪽 SELECT
UNION
UNION
의 2 번째 이후의SELECT
문DEPENDENT UNION
UNION
의 2 번째 이후의SELECT
문에서 외부 쿼리에 따라 달라집니다UNION RESULT
UNION
의 결과입니다.SUBQUERY
서브 쿼리의 첫번째 SELECT
DEPENDENT SUBQUERY
서브 쿼리의 첫번째 SELECT
에서 외부 쿼리에 따라 달라집니다DERIVED
파생 테이블 SELECT
(FROM
절의 서브 쿼리)MATERIALIZED
실체화 된 서브 쿼리 UNCACHEABLE SUBQUERY
결과를 캐시하지 못하고 외부 쿼리의 행마다 재평가 될 필요가있는 서브 쿼리 UNCACHEABLE UNION
캐시 불가능한 서브 쿼리 ( UNCACHEABLE SUBQUERY
를 참조하십시오)에 속하는UNION
의 2 번째 이후의 SELECTDEPENDENT
는 일반적으로 상관 관계 서브 쿼리의 사용을 보여줍니다. 섹션 13.2.10.7 "상관 서브 쿼리" 를 참조하십시오.DEPENDENT SUBQUERY
의 평가는UNCACHEABLE SUBQUERY
의 평가와는 다릅니다.DEPENDENT SUBQUERY
의 경우 외부 문맥의 변수가 다른 값의 각 세트 당 한 번만 서브 쿼리가 다시 평가됩니다.UNCACHEABLE SUBQUERY
의 경우 외부 컨텍스트의 각 행에 서브 쿼리가 다시 평가됩니다.서브 쿼리 캐시 가능성은 쿼리 캐시에 쿼리 결과 캐시 (이에 대해서는 섹션 8.9.3.1 "쿼리 캐시 동작" 에서 설명합니다)와 다릅니다. 서브 쿼리 캐시는 쿼리 실행 중에 이루어 쿼리 캐시는 쿼리의 실행이 종료 한 후에 만 결과를 저장하는 데 사용됩니다.
table
출력 행에서 참조하는 테이블의 이름입니다. 이것도 다음 값 중 하나가 될 수 있습니다.
<union
: 줄은M
,N
>M
과N
의id
값이있는 행의 합집합을 참조합니다.<derived
: 줄은N
>N
의id
값이있는 행의 파생 테이블 결과를 볼 수 있습니다. 파생 테이블은 예를 들어FROM
절의 서브 쿼리의 결과 등입니다.<subquery
: 줄은N
>N
의id
값이있는 행의 실체화 된 서브 쿼리의 결과를 볼 수 있습니다. 섹션 8.2.1.18.2 "서브 쿼리 구체화에 의한 서브 쿼리의 최적화" 를 참조하십시오.
partitions
쿼리에서 레코드가 일치되는 파티션. 이 컬럼은
PARTITIONS
키워드가 사용되는 경우에만 표시됩니다. 분할되지 않은 테이블의 경우이 값은NULL
입니다. 섹션 19.3.5 "파티션에 대한 정보를 얻기" 를 참조하십시오.type
결합 형. 다양한 형태의 설명은 "
EXPLAIN
결합 형 "을 참조하십시오.possible_keys
possible_keys
컬럼은 MySQL이 테이블의 행의 검색에 사용하기 위해 선택할 수있는 인덱스를 나타냅니다. 이 컬럼은EXPLAIN
의 출력에 표시되는 테이블의 순서에 전혀 의존하지 않습니다. 즉,possible_keys
의 키의 일부는 생성 된 테이블의 순서로 실제로 사용하지 못할 수 있습니다.이 컬럼이
NULL
의 경우는 관련 인덱스가 없습니다. 이 경우WHERE
절을 조사하여 그 인덱스 구성에 적합한 컬럼을 참조하고 있는지 여부를 확인하여 쿼리 성능을 향상시킬 수 있습니다. 그 경우는 적절한 인덱스를 생성하고 다시EXPLAIN
으로 쿼리를 확인합니다. 섹션 13.1.7 "ALTER TABLE 구문" 을 참조하십시오.테이블에있는 인덱스를 확인하려면
SHOW INDEX FROM
을 사용합니다.tbl_name
key
key
컬럼은 MySQL이 실제로 사용하는 것을 결정한 키 (인덱스)를 보여줍니다. MySQL이 행을 조회하는 데 하나의possible_keys
인덱스를 사용하기로 결정하면 키 값으로 인덱스가 나열됩니다.key
는possible_keys
값에 존재하지 않는 인덱스를 지정하고있을 가능성이 있습니다. 이것은possible_keys
인덱스 아무도 행의 조회에 적합하지 않은 경우에 발생할 수 있지만 쿼리가 선택한 모든 컬럼이 다른 인덱스 컬럼입니다. 즉, 지정된 인덱스가 선택된 컬럼을 커버하기 위해 반환되는 행을 결정하는 데 사용되지 않지만, 인덱스 스캔 데이터 라인 스캔보다 효율적입니다.InnoDB
는 각 보조 인덱스와 함께 기본 키 값을 저장하기 위해InnoDB
는 쿼리에서 기본 키 선택하는 경우에도 보조 인덱스에서 선택된 컬럼을 커버 할 수 있습니다.key
가NULL
의 경우, MySQL은 쿼리를보다 효율적으로 수행하기 위해 사용하는 인덱스를 찾을 수 없습니다.MySQL에서
possible_keys
컬럼에 나타난 인덱스를 강제로 사용하게하거나 무시하려면 쿼리FORCE INDEX
,USE INDEX
또는IGNORE INDEX
를 사용합니다. 섹션 13.2.9.3 "인덱스 힌트 구문" 을 참조하십시오.MyISAM
테이블과NDB
테이블의 경우ANALYZE TABLE
을 실행하여 최적화가 더 적절한 인덱스를 선택하는 데 도움이됩니다.NDB
테이블의 경우, 이에 따라 분산 된 푸시 다운 조인 성능도 향상됩니다.MyISAM
테이블의 경우, myisamchk --analyze는ANALYZE TABLE
과 같은 일을 수행합니다. 섹션 7.6 "MyISAM 테이블의 보수와 크래쉬 복구" 를 참조하십시오.key_len
key_len
컬럼은 MySQL이 사용하는 것을 결정한 키의 길이를 나타냅니다.key
컬럼에NULL
로 표시된 경우,이 길이는NULL
입니다.key_len
값으로 MySQL이 실제로 사용하는 다중 키 파트 수를 확인할 수 있습니다.ref
ref
컬럼은 테이블에서 행을 선택하기 위해key
컬럼에 지정된 인덱스에 비교되는 컬럼 또는 상수를 나타냅니다.값이
func
의 경우, 사용되는 값은 특정 함수의 결과입니다. 어떤 함수 있는지 확인하려면EXPLAIN EXTENDED
다음에SHOW WARNINGS
를 붙여 사용합니다. 함수는 실제로는 산술 연산자와 같은 연산자 일 수 있습니다.rows
rows
컬럼은 MySQL이 쿼리를 실행하기 위해 조사 할 필요가 있다고 생각 행수를 나타냅니다.InnoDB
테이블의 경우, 이것은 추정치이며, 항상 정확하지 않을 수 있습니다.filtered
filtered
컬럼은 테이블 조건에 의해 필터링 된 테이블 행의 추정 비율을 나타냅니다. 즉,rows
는 조사되는 추정 행 수를 나타내고,rows
×filtered
/100
이 이전 테이블과 조인되는 행 수를 나타냅니다.EXPLAIN EXTENDED
를 사용하면이 열이 표시됩니다.Extra
이 컬럼은 MySQL이 쿼리를 해결하는 방법에 대한 정보가 포함되어 있습니다. 다양한 값에 대한 설명은 "
EXPLAIN
추가 정보 "를 참조하십시오.
EXPLAIN 결합 형
EXPLAIN
출력의 type
컬럼은 테이블의 결합 방법을 설명합니다. 다음 목록에 가장 적절한 형태에서 가장 잘못된 유형의 순서로 정렬 된 결합 형을 나타냅니다.
system
테이블에 행이 하나 밖에 없습니다 (= system 테이블). 이것은
const
결합 형의 특수한 케이스입니다.const
테이블에 일치하는 레코드가 최대 1 가지 쿼리를 시작할 때 읽습니다. 행이 하나 밖에 없기 때문에이 행의 열 값은 최적화의 나머지를 통해 상수로 간주 될 수 있습니다.
const
테이블은 한번 밖에 읽을 수 없기 때문에 매우 빠릅니다.const
는PRIMARY KEY
또는UNIQUE
인덱스의 모든 부분을 상수 값과 비교할 때 사용됩니다. 다음 쿼리는tbl_name
은const
테이블로 사용할 수 있습니다.SELECT * FROM
tbl_name
WHEREprimary_key
= 1; SELECT * FROMtbl_name
WHEREprimary_key_part1
= 1 ANDprimary_key_part2
= 2;eq_ref
이전 테이블의 행의 조합에 대해이 테이블에서 한 줄씩 읽습니다.
system
및const
형 이외에서 이것은 최적의 결합 형입니다. 이것은 결합 인덱스의 모든 파트가 사용되어 인덱스가PRIMARY KEY
또는UNIQUE NOT NULL
인덱스 인 경우에 사용됩니다.eq_ref
는=
연산자를 사용하여 비교되는 인덱스 설정된 컬럼에 사용할 수 있습니다. 비교 값은 상수 또는이 테이블 이전에 읽은 테이블의 컬럼을 사용하는 식을 지정할 수 있습니다. 다음의 예에서는 MySQL은eq_ref
조인을 사용하여ref_table
을 처리 할 수 있습니다.SELECT * FROM
ref_table
,other_table
WHEREref_table
.key_column
=other_table
.column
; SELECT * FROMref_table
,other_table
WHEREref_table
.key_column_part1
=other_table
.column
ANDref_table
.key_column_part2
= 1;ref
이전 테이블의 행의 조합에 대해 일치하는 인덱스 값을 가진 모든 행이이 테이블에서 읽습니다.
ref
조인 키의 왼쪽 프리픽스 만 사용되는 경우, 또는 키가PRIMARY KEY
나UNIQUE
인덱스가 아닌 경우 (즉, 결합에서 키 값에 따라 단일 행을 선택할 수없는 경우)에 사용 됩니다. 사용되는 키가 몇 줄 밖에 일치하지 않는 경우, 이것은 적절한 결합 형입니다.ref
는=
또는<=>
연산자를 사용하여 비교되는 인덱스 설정된 컬럼에 사용할 수 있습니다. 다음의 예에서는 MySQL은ref
조인을 사용하여ref_table
을 처리 할 수 있습니다.SELECT * FROM
ref_table
WHEREkey_column
=expr
; SELECT * FROMref_table
,other_table
WHEREref_table
.key_column
=other_table
.column
; SELECT * FROMref_table
,other_table
WHEREref_table
.key_column_part1
=other_table
.column
ANDref_table
.key_column_part2
= 1;fulltext
결합은
FULLTEXT
인덱스를 사용하여 수행됩니다.ref_or_null
이 결합 형은
ref
와 유사하지만, MySQL이NULL
값을 갖는 행의 추가 검색을 수행 할 추가됩니다. 이 결합 형의 최적화는 대부분의 경우에 하위 쿼리의 해결에 사용됩니다. 다음의 예에서는 MySQL은ref_or_null
조인을 사용하여ref_table
을 처리 할 수 있습니다.SELECT * FROM
ref_table
WHEREkey_column
=expr
ORkey_column
IS NULL;섹션 8.2.1.8 "IS NULL 최적화" 를 참조하십시오.
index_merge
이 결합 형은 인덱스 병합 최적화가 사용 된 것을 나타냅니다. 이 경우 출력 행의
key
컬럼은 사용 된 인덱스의 목록이 포함되어key_len
는 사용 된 인덱스의 최대 키 파트의 목록이 포함됩니다. 자세한 내용은 섹션 8.2.1.4 "인덱스 병합 최적화" 를 참조하십시오.unique_subquery
이 형식은 다음과 같은 형식의
IN
서브 쿼리의ref
를 대체합니다.value
IN (SELECTprimary_key
FROMsingle_table
WHEREsome_expr
)unique_subquery
는 효율성을 위해 서브 쿼리를 완전히 대체 단순한 인덱스 조회 기능입니다.index_subquery
이 결합 형은
unique_subquery
와 비슷합니다.IN
서브 쿼리를 대체하지만, 다음과 같은 형식의 서브 쿼리의 고유하지 않은 인덱스에 대해 작동합니다.value
IN (SELECTkey_column
FROMsingle_table
WHEREsome_expr
)range
행을 선택하기위한 인덱스를 사용하여 특정 범위에있는 행 만 검색됩니다. 출력 행의
key
컬럼은 사용 된 인덱스를 나타냅니다.key_len
는 사용 된 최대 인덱스 부분이 포함됩니다. 이 형식의ref
컬럼은NULL
입니다.range
는=
<<>
,>
, >>=
,<
,<=
,IS NULL
,<=>
,BETWEEN
또는IN()
연산자 중 하나를 사용하여 키 컬럼을 상수와 비교하는 경우에 사용 수 있습니다.SELECT * FROM
tbl_name
WHEREkey_column
= 10; SELECT * FROMtbl_name
WHEREkey_column
BETWEEN 10 and 20; SELECT * FROMtbl_name
WHEREkey_column
IN (10,20,30); SELECT * FROMtbl_name
WHEREkey_part1
= 10 ANDkey_part2
IN (10,20,30);index
index
결합 형 타입은 인덱스가 스캔되는 것을 제외하고,ALL
과 동일합니다. 이것은 두 가지 방법으로 이루어집니다.인덱스가 쿼리 첨부 인덱스에서 사용하면 테이블에서 필요한 모든 데이터를 만족시킬 수있는 경우 인덱스 트리 만 검색됩니다. 이 경우
Extra
컬럼에Using index
라고 표시됩니다. 인덱스는 일반 테이블 데이터보다 작기 때문에 인덱스 만 스캔은 일반적으로ALL
보다 빠릅니다.풀 테이블 스캔은 인덱스에서 읽기를 사용하여 인덱스 순서로 데이터 행을 조회하여 수행됩니다.
Extra
컬럼에Uses index
가 표시되지 않습니다.
MySQL은 쿼리에서 단일 인덱스의 일부인 컬럼 만이 사용되는 경우이 결합 형을 사용할 수 있습니다.
ALL
풀 테이블 스캔은 이전 테이블의 행의 조합에 대해 실행됩니다. 이것은 일반적으로 테이블이
const
로 표시되지 않은 첫 번째 테이블 인 경우에는 적합하지 않고, 보통 다른 모든 경우에 현저 부적절합니다. 일반적으로 상수 값 또는 이전 테이블에서 컬럼 값에 따라 테이블에서 행의 취득을 가능하게하는 인덱스를 추가하면ALL
을 피할 수 있습니다.
EXPLAIN 추가 정보
EXPLAIN
출력의 Extra
컬럼은 MySQL이 쿼리를 해결하는 방법에 대한 정보가 포함되어 있습니다. 다음 목록은이 컬럼에 표시 될 수있는 값에 대해 설명합니다. 쿼리를 가능한 한 빠르게하려면, Using filesort
및 Using temporary
의 Extra
값에주의합니다.
Child of '
table
'pushed join @ 1이 테이블은 NDB 커널로 푸시 다운 할 수있는 결합의
table
의 자식으로 참조됩니다. MySQL Cluster에서 푸시 다운 된 결합이 유효한 경우에만 적용됩니다. 자세한 내용과 예제는ndb_join_pushdown
서버 시스템 변수의 설명을 참조하십시오.const row not found
SELECT ... FROM
같은 쿼리의 경우, 테이블은 비어있었습니다.tbl_name
Deleting all rows
DELETE
대해 일부 스토리지 엔진 (MyISAM
등)은 쉽고 빠르게 모든 행 테이블을 삭제하는 핸들러 메소드를 지원하고 있습니다. 이Extra
값은 엔진이 최적화가 사용 된 경우에 표시됩니다.Distinct
MySQL은 개별 값을 검색하기 위해 첫 번째로 일치하는 행을 찾으면 현재의 행의 조합에 관하여 더 줄 검색을 중지합니다.
FirstMatch (
tbl_name
)tbl_name
은 준 결합 FirstMatch 결합 바로 가기 전략이 사용됩니다.Full scan on NULL key
이것은 옵티마이 저가 인덱스 조회 접근 방법을 사용할 수없는 경우 대체 전략으로 서브 쿼리의 최적화로 이루어집니다.
Impossible HAVING
HAVING
절은 항상 false로 어떤 행을 선택할 수 없습니다.Impossible WHERE
WHERE
절은 항상 false로 어떤 행을 선택할 수 없습니다.Impossible WHERE noticed after reading const tables
MySQL은 모든
const
(및system
) 테이블을 읽고WHERE
절이 항상 false임을 알립니다.LooseScan (
m
..n
)준 결합 LooseScan 전략이 사용됩니다.
m
및n
은 키 파트 번호입니다.Materialize
,Scan
MySQL 5.6.7 이전에는, 이것은 하나의 실체화 된 임시 테이블의 사용을 보여줍니다.
Scan
이 있으면 테이블의 읽기에 임시 테이블 인덱스는 사용되지 않습니다. 그렇지 않은 경우는 인덱스 조회가 사용됩니다. 또한Start materialize
항목을 참조하십시오.MySQL 5.6.7 현재 실체화는
MATERIALIZED
의select_type
값이있는 행과<subquery
의N
>table
값이있는 행으로 표시됩니다.No matching min / max row
SELECT MIN(...) FROM ... WHERE
같은 쿼리의 조건을 만족하는 행이 없습니다.condition
no matching row in const table
결합 된 쿼리에서 빈 테이블 또는 고유 인덱스 조건을 만족하는 행이없는 테이블이있었습니다.
No matching rows after partition pruning
DELETE
또는UPDATE
에 대해 최적화 파티션 정리 후 삭제 또는 업데이트하는 것이 아무것도 발견하지 않았습니다. 그것은SELECT
문Impossible WHERE
의미가 비슷합니다.No tables used
쿼리에
FROM
절이 없거나FROM DUAL
절이 있습니다.INSERT
또는REPLACE
문에서SELECT
부분이없는 경우EXPLAIN
에이 값이 표시됩니다. 예를 들어,EXPLAIN INSERT INTO t VALUES(10)
에 대해 그것은EXPLAIN INSERT INTO t SELECT 10 FROM DUAL
와 동일하기 때문에 표시됩니다.Not exists
MySQL은 쿼리에 대한
LEFT JOIN
최적화를 실행할 수있어LEFT JOIN
조건에 일치하는 1 개의 행이 발견되면 이전 행의 조합이 테이블에 더 행을 조사하지 않습니다. 이것은 이렇게 최적화 쿼리 유형의 예입니다.SELECT * FROM t1 LEFT JOIN t2 ON t1.id = t2.id WHERE t2.id IS NULL;
t2.id
가NOT NULL
로 정의되어 있다고합니다. 이 경우, MySQL은t1
을 스캔하고t1.id
값을 사용하여t2
의 행을 조회합니다. MySQL이t2
에 일치하는 행을 찾으면t2.id
는NULL
이되지 않는 것을 알고 있기 때문에 같은id
값을 가진t2
의 나머지 행을 스캔하지 않습니다. 즉,t1
의 각 행에 대해, MySQL은t2
에서 실제로 일치하는 행 수에 관계없이t2
에서 하나의 조회 만 수행해야합니다.Range checked for each record (index map :
N
)MySQL은 사용에 적합한 인덱스를 찾지 못했지만, 이전 테이블에서 컬럼 값을 발견 한 후 일부 인덱스를 사용할 수 있는지 알 수있었습니다. 이전 테이블의 행의 조합에 대해 MySQL은
range
또는index_merge
접근 방식을 사용하여 행을 검색 할 수 있는지 여부를 확인합니다. 이것은 매우 빠르지 않지만, 인덱스가 전혀없는 결합의 실행보다 빠릅니다. 이전 테이블의 모든 컬럼 값을 알고 있으며, 상수로 간주되는 것을 제외하고, 적용 기준은 섹션 8.2.1.3 "range 최적화" 과 섹션 8.2.1.4 "인덱스 병합 최적화" 에 설명 된 있다 같습니다.인덱스는 테이블의
SHOW INDEX
에 표시된 순서대로 1부터 번호가 매겨집니다. 인덱스 맵 값N
은 후보 인덱스를 나타내는 비트 마스크입니다. 예를 들어,0x19
(2 진수 11001)의 값은 인덱스 1, 4 및 5가 고려되는 것을 나타냅니다.scanned
N
databases이것은 섹션 8.2.4 "INFORMATION_SCHEMA 쿼리 최적화" 에 설명 된대로 서버가
INFORMATION_SCHEMA
테이블의 쿼리를 처리 할 때 사용하는 디렉토리 스캔 수를 나타냅니다.N
의 값은 0 또는all
입니다.Select tables optimized away
쿼리는 모든 인덱스를 사용하여 해결 된 집계 함수 (
MIN()
,MAX()
) 또는COUNT(*)
만 포함되어 있지만GROUP BY
절은 포함되지 않았습니다. 최적화는 1 행만 반환한다고 판단했습니다.Skip_open_table
,Open_frm_only
,Open_trigger_only
,Open_full_table
이 값은 섹션 8.2.4 "INFORMATION_SCHEMA 쿼리 최적화" 에 설명하도록
INFORMATION_SCHEMA
테이블에 대한 쿼리에 적용 할 파일 오픈 최적화를 보여줍니다.Skip_open_table
: 테이블 파일을 열 필요가 없습니다. 데이터베이스 디렉토리를 검색하여 쿼리에서 이미 정보를 사용할 수 있도록되어 있습니다.Open_frm_only
: 테이블의.frm
파일 만 열어야합니다.Open_trigger_only
: 테이블의.TRG
파일 만 열어야합니다.Open_full_table
: 최적화되지 않은 정보의 조회..frm
,.MYD
, 그리고.MYI
파일을 열어야합니다.
Start materialize
,End materialize
,Scan
MySQL 5.6.7 이전에는, 이것은 여러 실체화 된 임시 테이블의 사용을 보여줍니다.
Scan
이 있으면 테이블의 읽기에 임시 테이블 인덱스는 사용되지 않습니다. 그렇지 않은 경우는 인덱스 조회가 사용됩니다. 또한Materialize
항목을 참조하십시오.MySQL 5.6.7 현재 실체화는
MATERIALIZED
의select_type
값이있는 행과<subquery
의N
>table
값이있는 행으로 표시됩니다.Start temporary
,End temporary
이것은 준 결합 중복 제거 전략 임시 테이블의 사용을 보여줍니다.
unique row not found
SELECT ... FROM
같은 쿼리의 경우 테이블에tbl_name
UNIQUE
인덱스 나PRIMARY KEY
한정된 행이 없습니다.Using filesort
MySQL은 정렬 된 순서로 행을 검색하는 방법을 찾기 위해 추가 경로를 실행해야합니다. 정렬은 결합 형에 따라 모든 행을 진행 소트 키와
WHERE
절에 일치하는 모든 행에 대해 행에 대한 포인터를 저장하고 실행됩니다. 다음 키가 정렬되고 정렬 순서에서 행이 검색됩니다. 섹션 8.2.1.15 "ORDER BY 최적화" 를 참조하십시오.Using index
실제 행을 읽기위한 추가 탐색을 수행 할 필요가없고, 인덱스 트리의 정보만을 사용하여 테이블에서 컬럼 정보를 검색합니다. 이 전략은 쿼리에서 단일 인덱스의 일부분 인 컬럼만을 사용하는 경우에 사용할 수 있습니다.
Extra
컬럼에Using where
라고 표시된 경우 키 값 조회를 실행하기 위해 인덱스가 사용되는 것을 의미합니다.Using where
가없는 경우 옵티마이 저가 인덱스를 읽어 데이터 행 읽기를 피할 수 있지만, 그것을 조회로 사용하지 않습니다. 예를 들어, 인덱스가 쿼리 첨부 인덱스 인 경우, 최적화는 그것을 조회에 사용하지 않고 그것을 검사 할 수 있습니다.사용자 정의 클러스터링 된 인덱스를 가지는
InnoDB
테이블의 경우 인덱스는Extra
컬럼에Using index
가없는 경우에도 사용할 수 있습니다. 이는type
이index
에서key
가PRIMARY
의 경우입니다.Using index condition
인덱스 튜플에 액세스 먼저 그들을 테스트하여 모든 테이블 행을 읽을 여부를 판단하여 테이블을 읽습니다. 이와 같이 요구하지 않는 한 모든 테이블 행 읽기를 지연 ( "푸시 다운")하는 인덱스 정보가 사용됩니다. 섹션 8.2.1.6 "인덱스 조건문 푸시 다운 최적화" 를 참조하십시오.
Using index for group-by
Using index
테이블 액세스 방법과 마찬가지로Using index for group-by
은 MySQL이 실제 테이블에 추가 디스크 액세스를하지 않고GROUP BY
또는DISTINCT
쿼리의 모든 컬럼을 얻기 위해 사용할 수있는 인덱스 을 찾아 냈다는 것을 나타냅니다. 또한 각 그룹에 대해 약간 인덱스 엔트리 만이 읽을 수 있도록 색인을 가장 효율적으로 사용됩니다. 자세한 내용은 섹션 8.2.1.16 "GROUP BY 최적화" 를 참조하십시오.Using join buffer (Block Nested Loop)
,Using join buffer (Batched Key Access)
초기의 결합에서의 테이블은 각 부분에 결합 버퍼에 읽힌 해당 행이 버퍼에서 사용되어 현재 테이블의 결합이 실행됩니다.
(Block Nested Loop)
는 Block Nested Loop 알고리즘의 사용을 나타내며(Batched Key Access)
는 Batched Key Access 알고리즘의 사용을 보여줍니다. 즉,EXPLAIN
출력의 이전 행의 테이블에서 키가 버퍼링되어Using join buffer
가 표시된 라인에 의해 나타내지는 테이블에서 일치하는 행이 일괄 인출됩니다.Using MRR
테이블은 Multi-Range Read 최적화 전략을 사용하여 읽습니다. 섹션 8.2.1.13 "Multi-Range Read 최적화" 를 참조하십시오.
Using sort_union(...)
,Using union(...)
,Using intersect(...)
이들은
index_merge
결합 형 인덱스 스캔이 어떻게 병합하는 방법을 보여줍니다. 섹션 8.2.1.4 "인덱스 병합 최적화" 를 참조하십시오.Using temporary
쿼리를 해결하기 위해 MySQL은 결과를 저장할 임시 테이블을 작성해야합니다. 이것은 일반적으로 쿼리에 컬럼을 다르게 표시하는
GROUP BY
절과ORDER BY
절이 포함 된 경우에 발생합니다.Using where
WHERE
절은 다음 테이블에 일치하거나 클라이언트에 전송되는 행을 제한하는 데 사용됩니다. 구체적으로 테이블에서 모든 행을 반입하거나 조사 할 의도가없는 한,Extra
값이Using where
가 아니고, 테이블 결합 형이ALL
또는index
인 경우, 쿼리에 어떤 오류가있을 수 있습니다.Using where with pushed condition
이 항목은
NDB
테이블에만 적용됩니다. 즉, MySQL Cluster가 조건문 푸시 다운 최적화를 사용하여 인덱스 설정되지 않은 컬럼과 상수의 직접 비교의 효율성을 향상시킵니다. 그런 경우 조건이 클러스터의 데이터 노드에 "푸시 다운"된 모든 데이터 노드에서 동시에 평가됩니다. 이렇게하면 일치하지 않는 행을 네트워크를 통해 보낼 필요가 없어지고, 조건문 푸시 다운을 사용할 수 있지만 사용하지 않는 경우보다 그러한 쿼리를 5 - 10 배 속도를 높일 수 있습니다. 자세한 내용은 섹션 8.2.1.5 "엔진 조건문 푸시 다운 최적화" 를 참조하십시오.
EXPLAIN 출력의 해석
EXPLAIN
출력의 rows
컬럼의 값을 곱한 값을 취득함으로써 결합이 어느 정도 적합한지를 나타내는 적절한 기준을 얻을 수 있습니다.이것은 쿼리를 실행하기 위해 MySQL을 조사 할 필요가있는 행수를 대략적으로 보여주는 것입니다. max_join_size
시스템 변수가 쿼리를 제한하려면이 행의 곱은 어떻게 여러 테이블 SELECT
문을 실행하고 어느 것을 중지 할 것인지 결정하는 데에도 사용됩니다. 섹션 8.11.2 "서버 파라미터의 튜닝」 을 참조하십시오.
다음 예제는 EXPLAIN
에 의해 얻어진 정보에 따라 여러 테이블 결합을 단계적으로 최적화하는 방법을 보여줍니다.
여기에 표시된 SELECT
문이 있으며, EXPLAIN
을 사용하여 조사 할 생각이라고합니다.
EXPLAIN SELECT tt.TicketNumber, tt.TimeIn, tt.ProjectReference, tt.EstimatedShipDate, tt.ActualShipDate, tt.ClientID, tt.ServiceCodes, tt.RepetitiveID, tt.CurrentProcess, tt.CurrentDPPerson, tt.RecordVolume, tt.DPPrinted, et.COUNTRY, et_1.COUNTRY, do.CUSTNAME FROM tt, et, et AS et_1, do WHERE tt.SubmitTime IS NULL AND tt.ActualPC = et.EMPLOYID AND tt.AssignedPC = et_1.EMPLOYID AND tt.ClientID = do.CUSTNMBR;
이 예에서는 다음과 같이 가정하고 있습니다.
비교 대상의 열은 다음과 같이 선언되어 있습니다.
테이블 컬럼 데이터 형 tt
ActualPC
CHAR (10)
tt
AssignedPC
CHAR (10)
tt
ClientID
CHAR (10)
et
EMPLOYID
CHAR (15)
do
CUSTNMBR
CHAR (15)
테이블에는 다음 인덱스가 있습니다.
테이블 인덱스 tt
ActualPC
tt
AssignedPC
tt
ClientID
et
EMPLOYID
(기본 키)do
CUSTNMBR
(기본 키)tt.ActualPC
값은 균일하게 분포되어 있지 않습니다.
처음에는 최적화가 실행되기 전에는 EXPLAIN
문에서 다음과 같은 정보가 생성되었습니다.
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 do ALL PRIMARY NULL NULL NULL 2135 et_1 ALL PRIMARY NULL NULL NULL 74 tt ALL AssignedPC, NULL NULL NULL 3872 ClientID, ActualPC Range checked for each record (index map : 0x23)
각 테이블의 type
이 ALL
이기 때문에이 출력은 MySQL이 모든 테이블, 즉 모든 행의 조합 데카르트를 생성하는 것을 보여줍니다. 이것은 각 테이블의 행 수를 곱한 값을 조사 할 필요가 있기 때문에 상당히 시간이 걸립니다. 이 케이스의 경우이 곱이 74 × 2135 × 74 × 3872 = 45,268,558,720 줄 것입니다. 테이블이 더 크면 얼마나 시간이 걸려 있었는지 쉽게 상상이갑니다.
여기에서 문제의 하나는 열이 동일한 형태와 크기로 선언 된 경우, MySQL은 컬럼에 인덱스를보다 효율적으로 사용할 수있는 것입니다. 이 컨텍스트에서는 VARCHAR
과 CHAR
같은 크기로 선언되어 있다면, 그들은 동일한 것으로 간주됩니다. tt.ActualPC
는 CHAR (10)
으로 선언되어있어 et.EMPLOYID
는 CHAR (15)
이므로 길이의 불일치가 있습니다.
이 컬럼 길이의 불일치를 수정하려면 ALTER TABLE
을 사용하여 ActualPC
을 10 자에서 15 자로 길어합니다.
mysql> ALTER TABLE tt MODIFY ActualPC VARCHAR (15);
이제 tt.ActualPC
와 et.EMPLOYID
은 모두 VARCHAR (15)
입니다. EXPLAIN
문을 다시 실행하면 다음과 같은 결과가 생성됩니다.
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC, NULL NULL NULL 3872 Using ClientID, where ActualPC do ALL PRIMARY NULL NULL NULL 2135 Range checked for each record (index map : 0x1) et_1 ALL PRIMARY NULL NULL NULL 74 Range checked for each record (index map : 0x1) et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1
이것은 완전하지는 않지만 훨씬 개선되고 있습니다. rows
값의 곱은 74의 계수만큼 줄어 듭니다. 이 버전은 몇 초에서 실행합니다.
두 번째 변경을 실행하여 tt.AssignedPC = et_1.EMPLOYID
과 tt.ClientID = do.CUSTNMBR
의 비교에서 컬럼 길이의 불일치를 해소 할 수 있습니다.
mysql>ALTER TABLE tt MODIFY AssignedPC VARCHAR (15)
->MODIFY ClientID VARCHAR (15);
변경 후 EXPLAIN
은 다음과 같은 출력을 생성합니다.
table type possible_keys key key_len ref rows Extra et ALL PRIMARY NULL NULL NULL 74 tt ref AssignedPC, ActualPC 15 et.EMPLOYID 52 Using ClientID, where ActualPC et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
이 시점에서 쿼리는 거의 가능한 한 충분히 최적화되어 있습니다. 나머지 문제는 MySQL은 기본적으로 tt.ActualPC
컬럼의 값이 균일하게 분포되어 있다고 가정하지만 tt
테이블에 그것이 맞지 않는 것입니다. 다행히 MySQL에 키 분포를 분석하도록 말할 쉽습니다.
mysql> ANALYZE TABLE tt;
추가 인덱스 정보에 의해 결합이 완벽하게되어, EXPLAIN
가 다음의 결과를 생성합니다.
table type possible_keys key key_len ref rows Extra tt ALL AssignedPC NULL NULL NULL 3872 Using ClientID, where ActualPC et eq_ref PRIMARY PRIMARY 15 tt.ActualPC 1 et_1 eq_ref PRIMARY PRIMARY 15 tt.AssignedPC 1 do eq_ref PRIMARY PRIMARY 15 tt.ClientID 1
EXPLAIN
출력의 rows
컬럼은 MySQL 결합 최적화의 학습에 의한 추측입니다. rows
의 곱과 쿼리가 반환 실제 행 수를 비교하여 수치가 실제와 가까운 여부를 확인하십시오. 수치가 꽤 다른 경우에는 SELECT
문에서 STRAIGHT_JOIN
을 사용하고 FROM
절에서 다른 순서로 테이블을 나열 해 보면 성능을 개선 할 수 있습니다.
경우에 따라서는 서브 쿼리에서 EXPLAIN SELECT
를 사용하면 데이터 변경 명령문을 실행할 수 있습니다. 자세한 내용은 섹션 13.2.10.8 "FROM 절의 서브 쿼리" 를 참조하십시오.