PostgreSQL
강의

#10 - EXPLAIN ANALYZE 제대로 읽기

중년개발자
중년개발자

@loxo

9일 전

15

postgresql01.png

PostgreSQL 성능 문제의 90%는 여기서 시작해서 여기서 끝난다

EXPLAIN ANALYZE는 처음 보면 외계어처럼 느껴지기 쉽다.
하지만 관점을 조금만 바꾸면, 이건 DB가 직접 써주는 성적표에 가깝다.

이 글에서는 **"모든 숫자를 이해하려 하지 말고, 무엇을 먼저 봐야 하는지"**에 집중한다.

sql
QUERY PLAN | -----------------------------------------------------------------------------------------------------------------------------------------------------------------+ Nested Loop (cost=0.42..14.33 rows=69 width=563) (actual time=0.087..0.198 rows=52 loops=1) | -> Index Only Scan using boards_pkey on boards b (cost=0.14..2.36 rows=1 width=16) (actual time=0.052..0.054 rows=1 loops=1) | Index Cond: (id = '019baab4-6b61-7d6d-a9c3-95edf906f976'::uuid) | Heap Fetches: 1 | -> Index Scan using posts_p1_board_id_category_is_pinned_id_idx on posts_p1 p (cost=0.27..11.28 rows=69 width=563) (actual time=0.025..0.084 rows=52 loops=1)| Index Cond: (board_id = '019baab4-6b61-7d6d-a9c3-95edf906f976'::uuid) | Planning Time: 1.419 ms | Execution Time: 0.268 ms |

1. EXPLAIN ANALYZE는 무엇을 해주는 도구인가

간단히 말하면:

  • EXPLAIN → DB가 이렇게 실행할 거야 라고 미리 말해주는 것
  • EXPLAIN ANALYZE진짜로 실행해보고 결과를 알려주는 것
sql
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 10;

이 명령을 실행하면 PostgreSQL은:

  1. 실제로 쿼리를 실행하고
  2. 어떤 방식으로 실행했는지
  3. 얼마나 시간이 걸렸는지
  4. 예상과 실제가 얼마나 달랐는지

를 전부 보여준다.

👉 그래서 성능 분석할 때는 EXPLAIN ANALYZE가 기본이다


2. 가장 먼저 봐야 할 것 3가지

처음부터 모든 항목을 이해하려고 하면 바로 포기하게 된다.
아래 3가지만 먼저 보면 된다.

1️⃣ 실행 시간 (Execution Time)

text
Execution Time: 120.345 ms
  • 이 쿼리가 얼마나 걸렸는지
  • 느린지 빠른지 판단하는 기준

일반적인 체감 기준:

  • 10ms 이하 → 매우 빠름
  • 10~100ms → 보통
  • 100ms 이상 → 개선 대상

2️⃣ 실제 처리된 행 수 (rows)

text
rows=5

이 숫자는 DB가 실제로 읽은 행의 개수다.

  • rows가 많다 → 많이 읽었다 → 느릴 가능성 큼
  • rows가 적다 → 효율적인 실행

👉 인덱스를 잘 탔는지 판단하는 핵심 지표


3️⃣ Scan 방식 (Seq Scan vs Index Scan)

EXPLAIN을 보면 이런 단어들이 보인다.

text
Seq Scan on orders Index Scan using idx_orders_user_id

의미는 단순하다.

  • Seq Scan: 테이블을 처음부터 끝까지 읽음
  • Index Scan: 인덱스를 통해 필요한 것만 읽음

흔히 하는 오해:

Seq Scan = 무조건 나쁨 ❌

사실은:

  • 테이블이 작으면 Seq Scan이 더 빠를 수도 있다
  • 중요한 건 얼마나 많은 rows를 읽었는가

3. cost를 어떻게 이해해야 하는가

EXPLAIN에 항상 나오는 이것:

text
cost=0.00..431.00

이 단계에서는 이렇게 이해하는 것이 가장 현실적이다.

  • cost는 DB 내부 추정치 (CPU 연산과 디스크 접근을 가중치로 계산한 PostgreSQL 내부 점수로, 실행 계획을 고르기 위해 사용된다)
  • 절대적인 시간(ms)이 아님
  • 다른 쿼리와 직접 비교하면 안 됨

👉 우선은 Execution Time과 rows에 집중하는 것이 가장 효율적이다


4. 예상(rows)과 실제(rows)가 다르면 위험 신호

text
rows=10 (actual rows=5000)

이런 경우는 매우 중요하다.

의미:

  • DB는 10건 나올 줄 알고 실행했는데
  • 실제로는 5000건이 나왔다

이러면:

  • 실행 계획이 잘못 선택될 수 있고
  • 갑자기 쿼리가 느려질 수 있다

주요 원인:

  • 통계 정보 오래됨
  • VACUUM / ANALYZE 부족
  • 데이터 분포가 한쪽으로 쏠림

5. 위에서 아래로 읽지 말 것

많이 하는 실수:

EXPLAIN 결과를 위에서부터 차례대로 읽는다

하지만 실제 실행 순서는 아래에서 위다.

  • 맨 아래 → 실제 데이터 접근
  • 맨 위 → 최종 결과 반환

👉 아래쪽이 진짜 중요한 부분


6. EXPLAIN ANALYZE 체크 순서

실무에서 이렇게만 봐도 된다.

  1. Execution Time이 느린가?
  2. rows가 예상보다 너무 많은가?
  3. Seq Scan이 나왔는데 테이블이 큰가?
  4. 인덱스가 있는데 Index Scan을 안 타는가?
  5. 예상 rows와 실제 rows 차이가 큰가?

이 중 하나라도 걸리면 → 개선 대상


7. EXPLAIN ANALYZE는 죄를 묻는 도구가 아니다

중요한 마인드셋 하나.

EXPLAIN ANALYZE는
"이 쿼리는 왜 이렇게 실행됐는지"
이유를 알려주는 도구다.

  • 잘못을 찾는 게 아니라
  • 이해를 쌓는 과정

처음엔 못 읽는 게 정상이다.
자주 보다 보면 패턴이 보이기 시작한다.

#PostgreSQL#EXPLAIN ANALYZE#SQL 성능 튜닝#데이터베이스 성능#쿼리 최적화

댓글 0

Ctrl + Enter를 눌러 등록할 수 있습니다
※ AI 다듬기는 내용을 정제하는 보조 기능이며, 최종 내용은 사용자가 확인해야 합니다.