Jerry's Log

Explain

contents

EXPLAIN 실행 계획(Execution Plan) 을 읽고 해석하는 방법에 대한 걸 알아보겠습니다.

EXPLAIN의 결과물은 쿼리에 대한 건강 검진 성적표라고 생각하시면 됩니다. 데이터베이스가 당신의 데이터를 찾기 위해 어떤 경로를 이용할지 정확히 보여줍니다. 데이터베이스(MySQL, PostgreSQL, Oracle 등)마다 출력 형식은 조금씩 다르지만, 핵심 개념은 동일합니다.

느린 쿼리를 고치기 위해 반드시 확인해야 할 중요한 지표들을 중심으로 설명하겠습니다.


1. 속도의 계층 구조 (The "Type" Column)

모든 EXPLAIN 계획에서 가장 중요한 컬럼은 보통 type (MySQL) 또는 access method (PostgreSQL)라고 불립니다. 이것은 데이터베이스가 행(Row)을 어떻게 가져오고 있는지를 알려줍니다.

다음은 최고(가장 빠름) 에서 최악(가장 느림) 순서의 계층 구조입니다.

순위 Type (접근 방식) 설명 판정
1 system / const 테이블에서 정확히 1개의 행만 읽음 (예: WHERE primary_key = 1). 🚀 즉시 완료 (Instant)
2 eq_ref Primary Key를 사용하여 테이블을 조인함. 매우 훌륭함
3 ref 고유하지 않은(Non-Unique) 인덱스 사용 (예: WHERE status = 'active'). 👍 좋음
4 range 인덱스의 특정 범위만 스캔 (예: WHERE date BETWEEN... 또는 id > 50). 👌 허용 가능
5 index 인덱스 트리 전체를 스캔 (데이터가 아닌 인덱스만 훑음). ⚠️ 느림
6 ALL / Seq Scan Full Table Scan (전체 테이블 스캔). 디스크에 있는 모든 행을 하나하나 다 읽음. 🛑 위험 (DANGER)

경험칙(Rule of Thumb): 데이터가 많은 테이블에서 ALL 이나 Seq Scan 이 보인다면, 인덱스가 누락된 것입니다.


2. "Rows" 컬럼 (추정치)

이 컬럼은 옵티마이저가 결과를 찾기 위해 검사해야 한다고 생각(추정) 하는 행의 개수를 나타냅니다.


3. "Key" 또는 "Possible Keys" 컬럼

문제 해결 팁:

  • possible_keys에는 인덱스가 있는데 keyNULL이라면? 데이터베이스가 인덱스를 타는 것보다 그냥 테이블 전체를 훑는 게 더 빠르다고 판단한 것입니다 (데이터가 아주 적은 테이블에서 흔함).
  • 둘 다 NULL이라면? 관련된 인덱스가 아예 없다는 뜻입니다.

4. "Extra" 컬럼 (MySQL 특화)

이 컬럼은 숨겨진 비용을 보여주며, 성능 문제의 원인이 자주 발견되는 곳입니다.


5. 실제 예시 (Real-World Example)

쿼리:

SELECT * FROM Users WHERE email = 'test@example.com';

시나리오 A: 나쁜 계획 (The Bad Plan)

id | select_type | table | type | possible_keys | key  | rows   | Extra
1  | SIMPLE      | Users | ALL  | NULL          | NULL | 100000 | Using where

시나리오 B: 좋은 계획 (인덱스 생성 후)

id | select_type | table | type  | possible_keys | key      | rows | Extra
1  | SIMPLE      | Users | const | idx_email     | idx_email| 1    | NULL

6. PostgreSQL의 특징: EXPLAIN ANALYZE

PostgreSQL에서 EXPLAIN만 쓰면 단순 추정치만 보여줍니다.

EXPLAIN ANALYZE를 실행하면, 데이터베이스가 실제로 쿼리를 실행한 뒤 추정치와 실제 소요 시간을 비교해 줍니다.

Seq Scan on users  (cost=0.00..183.00 rows=50 width=128) (actual time=0.015..2.450 rows=50 loops=1)

요약 체크리스트

  1. Type 확인: ALL인가요? (인덱스 추가 필요).
  2. Key 확인: 예상한 인덱스를 사용하고 있나요?
  3. Rows 확인: 숫자가 비상식적으로 높은가요?
  4. Extra 확인: Using filesortUsing temporary가 보이나요? (ORDER BYGROUP BY 최적화 필요).

references