책너두 (Real MySQL 8.0 1권) 44일차 (~472p)

요약

  • Extra 칼럼의 나머지 값들을 이해하게 됨.
    • Plan isn’t ready yet
      • 실행 중인 쿼리의 실행 계획을 살펴볼 때, 실행 계획이 수립하지 못한 상태임.
    • Range checked for each record(index map: N)
      • 인덱스 맵을 통해, 인덱스 레인지 스캔이 가능한지 레코드 단위로 체크함.
    • Recursive
      • WITH CTE 를 통해 재귀 쿼리를 사용할 수 있음.
    • Rematerialize
      • 래터럴 조인을 통해 임시 테이블을 매번 생성하여 저장함.
    • Select tables optimized away
      • 집계 함수 최적화가 가능한 경우임.

메모

Plan isn’t ready yet

  • MySQL 8.0 버전에서는 다른 커넥션에서 실행 중인 쿼리의 실행 계획을 살펴볼 수 있음.
    • SHOW PROCESSLIST; 를 통해 현재 프로세스가 실행 중인 쿼리를 볼 수 있음.
    • EXPLAIN FOR CONNECTION {CONNECTION ID} 명령을 통해 MySQL 옵티마이저가 의도된 인덱스를 사용하지 못해서 풀 스캔을 한다거나, 잘못된 실행 계획을 선택한 것이 아닌지 확인할 때 유용하게 사용할 수 있는 명령어임.
    • EXPLAIN FOR CONNECTION 명령 실행 시, Extra 칼럼에 “Plan is not ready yet” 메시지가 표시될 때가 있는데, 이 경우는 해당 커넥션에서 아직 쿼리의 실행 계획을 수립하지 못한 상태에서 명령을 실행한 것임.
      • 이 경우, 대상 커넥션의 쿼리가 실행 계획을 수립할 여유 시간을 좀 더 주고, 다시 명령을 실행하면 됨.

Range checked for each record(index map: N)

  • 두 개의 테이블을 조인하는 경우를 보자.
mysql> EXPLAIN
             SELECT *
             FROM employees e1, employees e2
             WHERE e2.emp_no >= e1.emp_no;
  • e1 테이블의 emp_no 가 작을 때는, e2 테이블을 풀 테이블 스캔으로 접근하고, e1 테이블의 emp_no 가 큰 값일 때는 e2 테이블을 인덱스 레인지 스캔으로 접근하는 형태를 수행하는 것이 최적의 조인 방법임.
    • 여기서, “레코드마다 인덱스 레인지 스캔을 체크한다” 고 할 수 있는데, 이것이 Extra 칼럼에 표시되는 “Range checked for each record” 의 의미임.

  • 위 그림은 “Range checked for each record” 실행 계획의 처리 시나리오를 그림으로 표현한 것임.
  • Extra 칼럼을 출력하면, (index map: 0x{16진수 value}) 이 표시됨.
    • 16진수를 2진수로 바꿨을 때, 이진 비트맵의 각 자릿수는 “CREATE TABLE tb_memeber …) 명령에 나열된 인덱스의 순번을 의미함.
    • ex) 0x19 = 0b11001
      • 각 자릿수에 1이 적힌 부분이 인덱스 후보로 선정됐음을 의미함.
      • p469에 예시가 잘 설명되어 있음.
      • 각 레코드 단위로 이 후보 인덱스 가운데, 어떤 인덱스를 사용할지 결정하게 됨.
        • 실제로 어떤 인덱스가 사용됐는지는 알 수 없음.
        • 단지, 각 비트맵의 자릿수가 1인 순번의 인덱스가 대상이라는 것만 알 수 있음.

Recursive

  • MySQL 8.0 버전부터 CTE(Common Table Expression)을 이용해 재귀 쿼리를 작성할 수 있게 됨.
  • MySQL 서버에서 재귀 쿼리는 WITH 구문을 이용한다.
  • WITH절 다음의 SELECT 쿼리에서는 WITH 절에서 생성된 내부 임시 테이블을(WHERE 절이 없으므로) 풀 스캔해서 결과를 반환함.
    • 이렇게 CTE를 이용한 재귀 쿼리의 실행 계획은 Extra 칼럼에 “Recursive” 구문이 표시됨.
    • p480에 예시가 잘 설명되어 있음.

WITH 구문을 이용한 CTE가 사용됐다고 무조건 Extra 칼럼에 “Recursive” 문구가 표시되는 것은 아님. WITH 구문이 재귀 CTE로 사용될 경우에만 “Recursive”가 표시됨. (p481에 예시가 설명되어 있음.)

Rematerialize

  • 8.0 버전부터 래터럴 조인(LATERAL JOIN) 기능이 추가됨.
    • 래터럴로 조인되는 테이블은 선행 테이블의 레코드별로 서브쿼리를 실행해서 그 결과를 임시 테이블에 저장한다.
      • 이 과정을 “Rematerializing” 라고 함.
      • p471에 예시가 잘 설명되어 있음. 11.4.7.6절 래터럴 조인을 참조하자.

Select tables optimized away

  • MIN() 또는 MAX()만 SELECT 절에 사용되거나 GROUP BY로 MIN(), MAX()를 조회하는 쿼리가 인덱스를 오름차순 또는 내림차순으로 1건만 읽는 형태의 최적화가 적용된다면, Extra 칼럼에 “Select tables optimized away”가 표시됨.
  • MyISAM 테이블에 대해서는 GROUP BY 없이 COUNT(*)만 SELECT 할 떄도 이런 형태의 최적화가 적용됨.
    • MyISAM 테이블은 전체 레코드 건수를 별도로 관리하기 때문에 인덱스나 데이터를 읽지 않고도 전체 건수를 빠르게 조회할 수 있음.
    • 하지만 MyISAM 테이블에서 WHERE 조건절이 있는 쿼리는 이런 최적화를 사용하지 못함.

댓글

Designed by JB FACTORY