실행 계획은 SQL을 처리하기 위해 옵티마이저가 선택한 테이블 접근 방식, 인덱스, 조인 순서와 조인 알고리즘 등의 계획입니다. MySQL에서는 EXPLAIN으로 예상 실행 계획을 확인하고, EXPLAIN ANALYZE로 쿼리를 실제 실행하여 예상치와 실제 처리 행 수 및 시간을 비교할 수 있습니다.
MySQL의 전통적인 EXPLAIN 결과는 다음 순서로 살펴볼 수 있습니다.
- 테이블 접근 순서: 출력된 테이블과
id를 통해 어떤 순서로 읽는지 확인합니다. type:const,eq_ref,ref,range,index,ALL등 접근 방식을 봅니다. 일반적으로ALL은 전체 테이블 스캔,index는 전체 인덱스 스캔을 의미합니다.possible_keys와key: 사용할 수 있었던 인덱스와 실제 선택된 인덱스를 비교합니다.key_len과ref: 복합 인덱스의 어느 부분을 사용했고 어떤 값과 비교하는지 확인합니다.rows와filtered: 읽을 것으로 예상한 행 수와 조건을 통과할 비율을 봅니다. 앞 단계의 행 수가 다음 조인에서 반복되므로 전체 작업량을 함께 판단해야 합니다.Extra:Using index,Using temporary,Using filesort등 추가 작업을 확인합니다.
특정 항목 하나만 보고 느린 쿼리라고 단정하면 안 됩니다. 작은 테이블의 전체 스캔은 합리적일 수 있고, Using filesort도 반환 건수가 적다면 큰 문제가 아닐 수 있습니다. 반대로 예상 행 수와 실제 행 수의 차이가 크면 통계가 부정확하거나 컬럼 간 상관관계를 옵티마이저가 잘못 추정했을 가능성이 있습니다.
type이ALL이면 반드시 인덱스를 추가해야 하나요?아닙니다. 테이블이 작거나 대부분의 행을 읽는 쿼리라면 전체 스캔이 더 저렴할 수 있습니다. 조회 빈도와 실제 처리 행 수, 실행 시간을 확인한 뒤 인덱스 추가 비용과 비교해야 합니다.
possible_keys에는 인덱스가 있는데key가 NULL인 이유는 무엇인가요?옵티마이저가 인덱스를 사용할 수는 있지만 전체 스캔이 더 저렴하다고 판단했거나, 통계와 데이터 분포상 선택도가 낮을 수 있습니다. 통계를 갱신하고 조건식의 타입·함수 사용 여부를 확인한 뒤
EXPLAIN ANALYZE로 실제 비용을 검증해야 합니다.
JPA 쿼리의 실행 계획은 어떻게 확인하나요?
Hibernate가 생성한 실제 SQL과 바인딩 값을 확인한 뒤 데이터베이스에서 동일한 조건으로
EXPLAIN을 실행해야 합니다.EXPLAIN ANALYZE는 쿼리를 실제로 실행하므로 운영 환경의 변경 쿼리나 무거운 쿼리에 무심코 사용하지 않도록 주의해야 합니다.