• MySQL매뉴얼
    • MySQL 5.6 매뉴얼
    • MySQL 5.1 매뉴얼
    • MySQL 5.0 매뉴얼
    • MySQL HA 매뉴얼
  • 기술문서
    • Xtrabackup 구성
    • 메모리 사용량 모니터링
  • 라이선스
  • 온라인문의
  • 회사소개
  • → 목 록 (MySQL5.6 한글메뉴얼) [close]
  • 1. MySQL 5.6 새로운 기능
  • 2. MySQL 설치 및 업그레이드
  • 3. MySQL Tutorial
  • 4. MySQL 프로그램
  • 5. MySQL 서버관리
  • 6. 보안
  • 7. 백업 및 복구
  • 8. 최적화
  • 1. 최적화 개요
    2. SQL문 최적화
    3. 최적화 및 인덱스
    4. 데이터베이스 구조의 최적화
    5. InnoDB 테이블의 최적화
    6. MyISAM 테이블의 최적화
    7. MEMORY 테이블 최적화
    8. 쿼리 실행 계획의 이해
    1. EXPLAIN으로 쿼리 최적화
    2. EXPLAIN 출력 포맷
    3. EXPLAIN EXTENDED 출력 포맷
    4. 쿼리 성능 추정
    5. 쿼리 최적화 제어
    9. 버퍼링과 캐시
    10. 잠금 작업의 최적화
    11. MySQL 서버의 최적화
    12. 성능 측정
  • 9. Language Structure(언어구조)
  • 10. Character Sets(Globalization)
  • 11. 데이터형(Data Types)
  • 12. 함수와 연산자
  • 13. SQL 문법
  • 14. InnoDB 스토리지 엔진
  • 15. 기타 스토리지 엔진
  • 16. 고가용성 및 확장성
  • 17. 리플리케이션
  • 18. MySQL Cluster
  • 19. 파티셔닝
  • 20. Stored Programs and Views
  • 21. INFORMATION_SCHEMA
  • 22. PERFORMANCE SCHEMA
  • 23. 컨넥터 및 API
  • 24. MySQL 확장
  • 25. MySQL Enterprise Edition
  • 26. MySQL Workbench
  • 27. 제약 및 제한
  • 28. MySQL 5.7 새로운 기능

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 번째 이후의 SELECT

    DEPENDENT 는 일반적으로 상관 관계 서브 쿼리의 사용을 보여줍니다. 섹션 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 WHERE primary_key = 1;
    
     SELECT * FROM tbl_name
       WHERE primary_key_part1 = 1 AND primary_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
       WHERE ref_table . key_column = other_table . column ;
    
     SELECT * FROM ref_table , other_table
       WHERE ref_table . key_column_part1 = other_table . column
       AND ref_table . key_column_part2 = 1;
    
  • ref

    이전 테이블의 행의 조합에 대해 일치하는 인덱스 값을 가진 모든 행이이 테이블에서 읽습니다. ref 조인 키의 왼쪽 프리픽스 만 사용되는 경우, 또는 키가 PRIMARY KEY 나 UNIQUE 인덱스가 아닌 경우 (즉, 결합에서 키 값에 따라 단일 행을 선택할 수없는 경우)에 사용 됩니다. 사용되는 키가 몇 줄 밖에 일치하지 않는 경우, 이것은 적절한 결합 형입니다.

    ref 는 = 또는 <=> 연산자를 사용하여 비교되는 인덱스 설정된 컬럼에 사용할 수 있습니다. 다음의 예에서는 MySQL은 ref 조인을 사용하여 ref_table 을 처리 할 수 있습니다.

     SELECT * FROM ref_table WHERE key_column = expr ;
    
     SELECT * FROM ref_table , other_table
       WHERE ref_table . key_column = other_table . column ;
    
     SELECT * FROM ref_table , other_table
       WHERE ref_table . key_column_part1 = other_table . column
       AND ref_table . key_column_part2 = 1;
    
  • fulltext

    결합은 FULLTEXT 인덱스를 사용하여 수행됩니다.

  • ref_or_null

    이 결합 형은 ref 와 유사하지만, MySQL이 NULL 값을 갖는 행의 추가 검색을 수행 할 추가됩니다. 이 결합 형의 최적화는 대부분의 경우에 하위 쿼리의 해결에 사용됩니다. 다음의 예에서는 MySQL은 ref_or_null 조인을 사용하여 ref_table 을 처리 할 수 있습니다.

     SELECT * FROM ref_table
       WHERE key_column = expr OR key_column IS NULL;
    

    섹션 8.2.1.8 "IS NULL 최적화" 를 참조하십시오.

  • index_merge

    이 결합 형은 인덱스 병합 최적화가 사용 된 것을 나타냅니다. 이 경우 출력 행의 key 컬럼은 사용 된 인덱스의 목록이 포함되어 key_len 는 사용 된 인덱스의 최대 키 파트의 목록이 포함됩니다. 자세한 내용은 섹션 8.2.1.4 "인덱스 병합 최적화" 를 참조하십시오.

  • unique_subquery

    이 형식은 다음과 같은 형식의 IN 서브 쿼리의 ref 를 대체합니다.

     value IN (SELECT primary_key FROM single_table WHERE some_expr )
    

    unique_subquery 는 효율성을 위해 서브 쿼리를 완전히 대체 단순한 인덱스 조회 기능입니다.

  • index_subquery

    이 결합 형은 unique_subquery 와 비슷합니다. IN 서브 쿼리를 대체하지만, 다음과 같은 형식의 서브 쿼리의 고유하지 않은 인덱스에 대해 작동합니다.

     value IN (SELECT key_column FROM single_table WHERE some_expr )
    
  • range

    행을 선택하기위한 인덱스를 사용하여 특정 범위에있는 행 만 검색됩니다. 출력 행의 key 컬럼은 사용 된 인덱스를 나타냅니다. key_len 는 사용 된 최대 인덱스 부분이 포함됩니다. 이 형식의 ref 컬럼은 NULL 입니다.

    range 는 = < <> , > , > >= , < , <= , IS NULL , <=> , BETWEEN 또는 IN() 연산자 중 하나를 사용하여 키 컬럼을 상수와 비교하는 경우에 사용 수 있습니다.

     SELECT * FROM tbl_name
       WHERE key_column = 10;
    
     SELECT * FROM tbl_name
       WHERE key_column BETWEEN 10 and 20;
    
     SELECT * FROM tbl_name
       WHERE key_column IN (10,20,30);
    
     SELECT * FROM tbl_name
       WHERE key_part1 = 10 AND key_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 절의 서브 쿼리" 를 참조하십시오.

서울시 강남구 영동대로 602 6층
TEL: 02-6061-0006  /  E: csr@mysqlkorea.com
주식회사 이노클러스터  등록번호 : 727-86-02261
Copyright © innocluster Co. ltd. all rights reserved