1. 참조
    1. https://velog.io/@jsj3282/23.-MySQL-실행-계획-실행-계획-분석
    2. https://cheese10yun.github.io/mysql-explian/
  2. EXPLAIN
    1. MySQL에서 쿼리의 실행 계획을 확인하는 명령어, 아무런 옵션 없이 사용된 경우 기본적인 쿼리 실행 계획만 보임

    2. EXPLAIN EXTENDED, EXPLAIN PARTITIONS 명령을 통해 더 상세한 실행 계획을 볼 수 있음

    3. EXPLAIN SELECT * FROM employees 처럼 EXPLAIN뒤에 확인하고자 하는 SELECT문을 작성해서 확인 가능

    4. 실행 예시

      EXPLAIN SELECT e.emp_no, e.first_name, s.from_date, s.salary
      FROM employees e, salaries s
      WHERE e.emp_no=s.emp_no
      limit 10;
      

      Untitled

      1. 쿼리 문자의 테이블 개수만큼 레코드가 표시됨
      2. 실행 순서는 위에서부터 아래로 실행됨 위쪽에서 출력된 레코드일수록 쿼리의 바깥 부분 또는 먼저 접근한 테이블
      3. INSERT/UPDATE/DELETE의 경우 확인할 방법이 없음 확인하기 위해서는 조건이 같은 SELECT문을 만들어서 확인
  3. 칼럼별 의미
    1. id

      // 첫번째 쿼리
      explain select e.emp_no, e.first_name, s.from_date, s.salary
      from employees e, salaries s
      where e.emp_no=s.emp_no;
      
      // 두번째 쿼리
      explain select
      ((select count(*) from employees)
      UNION ALL
      (select count(*) from departments)) as total_count;
      

      Untitled

      1. 각 테이블별로 가지는 고유번호
      2. 조인하는 경우에는 실행 계획은 따로 조회되지만 같은 id부여
      3. 서브쿼리형태로 조회하는 경우 각각 다른 id를 가짐
      4. 위 예제에서 첫번째 쿼리는 조인 테이블 실행 계획이며, 두번째 쿼리는 서브쿼리 테이블 실행 계획
    2. select_type

      1. SIMPLE

        explain select * from employees;
        

        Untitled

        1. UNION, 서브쿼리를 사용하지 않는 단순한 SELECT 쿼리일 경우
        2. 쿼리 문장이 복잡한 경우에도 SIMPLE인 단위 쿼리는 하나만 존재
        3. 일반적으로 제일 바깥 쿼리의 select_type이 SIMPLE
      2. PRIMARY

        explain select
        ((select count(*) from employees)
        UNION ALL
        (select count(*) from departments)) as total_count;
        

        Untitled

        1. UNION, 서브쿼리가 포함된 SELECT쿼리에서 가장 바깥쪽의 단위 쿼리의 select_type
        2. SIMPLE과 비슷하게 PRIMARY도 하나의 실행계획에서는 하나만 존재 가능
        3. 일반적으로 제일 바깥 단위 쿼리의 select_type
      3. UNION

        1. UNION으로 결합하는 경우 첫번째 단위 쿼리를 제외하고 두 번째 이후 단위부터 UNION 표시
      4. SUBQUERY

        1. FROM절 외에서 사용되는 서브쿼리의 경우 select_type
      5. DERIVED

        1. 서브 쿼리가 FROM절에 사용된 경우 MySQL은 항상 select_type이 DERIVED인 실행계획을 생성
        2. DERIVED는 단위 SELECT 쿼리의 실행 결과를 메모리나 디스크에 임시 테이블을 생성하는 것을 의미
    3. table

      // 첫번째 쿼리
      explain select emp_no from employees;
      
      // 두번째 쿼리
      explain select emp_no from employees e;
      

      Untitled

      1. 테이블 이름을 표시함
      2. SELECT문에서 테이블 이름을 수정한 경우 수정한 이름이 표시
    4. partitions

      1. 윈도우 함수 등에서 파티셔닝을 하는 경우 표시
      2. 좀 더 찾아보기
    5. type

      Untitled

      Untitled

    6. possible_key

      Untitled

      1. 인덱스를 활용하는 경우 어떤 인덱스를 사용하는지 표시
      2. 위 예시는 PK를 조건절로 사용했기 때문에 활용한 인덱스로 PK 표시
      3. 이용 가능성이 있는 인덱스 목록
    7. key_len

      explain select emp_no from employees where emp_no=10001;
      

      Untitled

      1. 인덱스의 각 레코드에서 인덱스를 몇 바이트까지 사용했는지 표시
      2. 그렇게 중요한 부분은 아닌데 인덱스가 너무 긴 경우도 성능에 영향을 줄 수 있음
    8. ref

      // 첫번째 쿼리
      explain select emp_no, first_name from employees where emp_no=10001;
      
      // 두번째 쿼리
      EXPLAIN SELECT e.emp_no, e.first_name, s.from_date, s.salary
      FROM employees e, salaries s
      WHERE e.emp_no=s.emp_no
      limit 10;
      

      Untitled

      1. type이 ref인 경우 참조 조건(동등 비교 조건 등)으로 어떤 값이 제공됐는지 확인
      2. 상수값일 경우 const
      3. 다른 테이블과 조인되는 경우 참조된 테이블의 컬럼이 표시됨
    9. rows

      1. 접근방식을 사용해서 몇 row를 가져왔는지 명시
      2. 어디까지나 계획이므로 실제 row개수는 달라질 수 있음
    10. filtered

      1. 데이터를 가져와 WHERE 검색 조건이 적용되면 몇행이 남는지 표시
      2. 여기도 계획이므로 결과값과는 달리질 수 있음
    11. extra

      explain select emp_no, fisrst_name from employees;
      

      Untitled

      Untitled