CodeGym /행동 /SQL SELF /쿼리 성능 분석 입문

쿼리 성능 분석 입문

SQL SELF
레벨 41, 레슨 0
사용 가능

실제 얘기로 시작해볼게. 네가 대형 쇼핑몰 플랫폼에서 개발자로 일한다고 상상해봐. 모든 게 완벽하게 돌아가는데, 한 가지 문제가 있어: 월간 매출 리포트가 너무 느리게 떠서, 유저들이 리포트 기다리는 동안 주문을 하나 더 할 수 있을 정도야. 너도 초조하고, 매니저도 초조하고, PostgreSQL 서버는 주전자처럼 끓고, 이거 완전 아포칼립스 분위기지. 근데 만약 한 번에 원인을 딱 찾아서 해결할 수 있다면 얼마나 좋겠어?

쿼리 성능 분석은 PostgreSQL의 건강검진 같은 거야. 어디가 "병목"(아픈 부분)인지 찾아내고, 그걸 고쳐서 유저 경험도 좋아지고 시스템 자원도 아낄 수 있지.

PostgreSQL에서 쿼리가 내부적으로 어떻게 동작할까?

예를 들어, 이런 간단한 쿼리를 쓴다고 해보자:

SELECT * FROM products WHERE price > 100;

PostgreSQL이 바로 데이터를 뽑는 게 아니야. 먼저 네 쿼리를 분석하고, 어떻게 실행할지 계획을 세운 다음에 실제로 동작해.

쿼리 실행의 주요 단계:

  1. 파싱. PostgreSQL이 네 쿼리에 문법 오류가 있는지 체크하고, 중간 형태로 바꿔.
  2. 최적화. 쿼리 옵티마이저가 여러 실행 방법을 평가해서, 시간과 자원이 제일 적게 드는 "가장 싼" 방법을 골라.
  3. 실행. 서버가 선택된 플랜대로 실제로 데이터를 뽑아와.

"병목"이란 뭘까?

"병목"은 쿼리에서 전체 속도를 느리게 만드는 부분이야. 예상보다 시간이 오래 걸리거나 자원을 많이 먹는 연산이 있을 수 있지. 예를 들어, PostgreSQL이 인덱스를 안 쓰고 테이블 전체를 스캔(Seq Scan)하면 쿼리가 느려져. 아니면 데이터가 생각보다 많아서 정렬, 조인, 필터링에 시간이 엄청 걸릴 수도 있고.

이런 부분들이 바로 병목이야 — 이런 것부터 먼저 찾아서 최적화하는 게 좋아.

쿼리 성능 분석 도구들

PostgreSQL에는 쿼리 문제를 찾는 데 도움 되는 강력한 도구들이 있어:

  1. EXPLAIN 그리고 EXPLAIN ANALYZE. 이 명령어들은 PostgreSQL이 쿼리를 어떻게 실행할지 보여주거나, 실제로 실행해서 성능을 측정해줘.
  • EXPLAIN: 쿼리를 실제로 실행하지 않고 실행 계획만 보여줘.
  • EXPLAIN ANALYZE: 쿼리를 실행해서 실제 실행 계획과 시간 같은 메트릭을 보여줘.

EXPLAIN 사용 예시:

EXPLAIN SELECT * FROM products WHERE price > 100;

출력 결과:

Seq Scan on products  (cost=0.00..35.50 rows=5 width=72)
  Filter: (price > 100)

여기서 보면 "Seq Scan" — 테이블 전체를 스캔하고 있어서, 큰 테이블에는 비효율적이야.

  1. pg_stat_statements. 이건 추가 확장 기능인데, 실행된 쿼리들을 기록해줘. 이걸로 이런 걸 볼 수 있어:
  • 서버에서 어떤 쿼리들이 실행되고 있는지.
  • 각 쿼리에 얼마나 시간이 걸리는지.
  • 쿼리가 몇 줄을 반환하고, 자원을 얼마나 쓰는지.

pg_stat_statements를 켜려면:

  1. 확장 기능 활성화:
CREATE EXTENSION pg_stat_statements;
  1. PostgreSQL 설정하기: postgresql.conf 파일에 아래를 추가해:
   shared_preload_libraries = 'pg_stat_statements'
   pg_stat_statements.track = all
  1. PostgreSQL 재시작.

이제 쿼리 분석 가능:

SELECT * FROM pg_stat_statements ORDER BY total_time DESC LIMIT 5;

이렇게 하면 전체 실행 시간 기준으로 제일 "무거운" 쿼리 5개를 볼 수 있어.

  1. 느린 쿼리 로그. PostgreSQL이 너무 오래 걸리는 쿼리(예: 1초 이상)를 로그 파일에 기록하게 할 수 있어.

이걸 하려면 postgresql.conf에 이렇게 설정해:

log_min_duration_statement = 1000  # 밀리초 단위 (1초)

이제 느린 쿼리들이 PostgreSQL 로그에 저장돼.

성능 분석을 위한 주요 메트릭

쿼리 성능을 분석할 때 아래 핵심 메트릭을 꼭 봐야 해:

  1. 실행 시간. 쿼리 실행에 걸린 시간. 빠를수록 좋지.
  2. 행(row) 수. 쿼리가 예상보다 많은 행을 반환하거나 스캔하면 문제가 될 수 있어.
  3. 인덱스 사용. 인덱스를 써야 하는데 Seq Scan(전체 스캔)만 한다면 최적화 신호야.
  4. 버퍼/디스크 작업. 디스크를 많이 읽는 쿼리는 메모리만 쓰는 쿼리보다 느려.

이 지식, 실제로 어떻게 써먹을까?

예시 1: 느린 쿼리

100보다 비싼 상품을 다 뽑는 쿼리를 쓴다고 해보자:

SELECT * FROM products WHERE price > 100;
이 쿼리가 너무 느리게 실행돼서 EXPLAIN을 써봤더니:
Seq Scan on products  (cost=0.00..35.50 rows=5 width=72)
  Filter: (price > 100)

문제: price 컬럼에 인덱스가 없어서 테이블 전체를 스캔하고 있어.

해결법:

인덱스를 만들어줘:

CREATE INDEX idx_price ON products(price);

이제 쿼리가 Index Scan을 사용해:

Index Scan using idx_price on products  (cost=0.15..8.25 rows=5 width=72)
  Index Cond: (price > 100)

예시 2: pg_stat_statements로 느린 쿼리 찾기

아래 명령어로:

SELECT query, total_time, calls
FROM pg_stat_statements
ORDER BY total_time DESC
LIMIT 1;

실행 시간이 많이 걸리는 쿼리를 찾을 수 있어. EXPLAIN ANALYZE로 플랜을 보고, 수정해서 더 빠르게 만들 수 있지.

EXPLAIN, pg_stat_statements 등 이런 도구들을 쓰기 시작하면, 네 쿼리들이 훨씬 빨라지고 PostgreSQL 서버도 스위스 시계처럼 돌아갈 거야. 다음 강의에서는 EXPLAIN의 cost, rows, width 같은 파라미터를 파고들어서, 쿼리 실행 계획을 책처럼 읽는 법을 배울 거야.

2
과제
SQL SELF, 레벨 41, 레슨 0
잠금
EXPLAIN을 사용해서 쿼리 실행 계획 분석하기
EXPLAIN을 사용해서 쿼리 실행 계획 분석하기
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION