0Pricing
Coding Interview Prep · 강의

EXPLAIN 계획 읽기

쿼리 계획에서 스캔 유형, 조인 방식, 비용 추정치를 해석합니다.

EXPLAIN 계획 읽기은(는) CoddyKit의 무료 Coding Interview Prep 강의입니다. 이것은 4개 중 1번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Coding Interview Prep 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.

면접에서 EXPLAIN을 묻는 이유

시니어 면접 단계에 이르면 면접관은 쿼리를 작성하라는 질문을 멈추고 이 쿼리는 왜 느린가를 묻기 시작합니다. 이 질문에 답하는 도구가 EXPLAIN입니다.

EXPLAIN은 데이터베이스의 실행 계획을 보여 줍니다. 실행 계획은 계획 수립기가 SQL을 실행하기 위해 선택한 단계별 전략입니다. 어떤 테이블을 읽는지, 어떤 순서로 결합하는지, 각 단계의 비용이 대략 어느 정도인지 확인할 수 있습니다.

실행 계획을 읽을 수 있다는 것은 구문만이 아니라 데이터베이스 엔진을 이해하고 있음을 보여 줍니다. 바로 이 점이 면접관이 중급 개발자와 시니어 개발자를 구분할 때 확인하는 부분입니다.

EXPLAIN과 EXPLAIN ANALYZE 비교

두 가지 방식이 있으며, 면접관은 이 차이를 중요하게 봅니다.

  • EXPLAIN은 쿼리를 실행하지 않고 계획 수립기가 예상한 실행 계획을 보여 줍니다. 빠르고 안전합니다.
  • EXPLAIN ANALYZE는 쿼리를 실제로 실행하고, 예상값과 함께 실제 행 수와 실행 시간을 보고합니다.

가장 중요한 부분은 예상 행 수와 실제 행 수를 비교하는 것입니다. 큰 차이가 있다면 계획 수립기가 잘못된 통계 정보를 사용하고 있어 좋지 않은 선택을 내리고 있을 가능성이 큽니다.

주의하셔야 합니다. EXPLAIN ANALYZE는 쿼리를 실제로 실행하므로 롤백되는 트랜잭션으로 감싸지 않으면 INSERT 또는 UPDATE도 수행합니다.

EXPLAIN ANALYZE
SELECT * FROM orders WHERE customer_id = 42;

실행 계획 트리 읽는 법

실행 계획은 목록이 아니라 트리입니다. 가장 많이 들여쓰기된 노드는 먼저 실행되는 말단 노드이며, 결과는 최종 출력을 생성하는 루트까지 위쪽으로 흐릅니다.

안쪽에서 바깥쪽 순서로 읽으십시오. 가장 깊은 노드를 찾으면 그곳에서 실행이 시작됩니다. 각 상위 노드는 하위 노드가 내보내는 행을 받아 처리합니다.

면접에서는 다음과 같은 방식으로 설명하시면 됩니다. 먼저 이 테이블을 읽고, 해당 행이 이 결합으로 전달되며, 결합 결과가 정렬로 전달되고, 정렬 결과가 제한 단계로 전달됩니다. 이러한 아래에서 위로 올라가는 설명을 면접관은 듣고 싶어 합니다.

계획 노드의 구조

Postgres 실행 계획의 모든 노드에는 다음과 같은 핵심 수치가 표시됩니다:

  • cost=0.00..35.50 시작 비용..총 비용을 나타내며, 단위는 플래너의 임의 단위입니다
  • rows=1000 생성되는 행 수의 예상치입니다
  • width=64 행 하나의 평균 크기 예상치(바이트)입니다

첫 번째 비용은 시작 비용입니다(첫 번째 행이 나타나기 전에 수행하는 작업으로, 해시 테이블 구축 등이 해당합니다). 두 번째 비용은 모든 행을 반환하는 데 필요한 총 비용입니다. 총 비용이 높을수록 플래너가 예상한 상대적 비용이 큽니다.

Seq Scan on orders  (cost=0.00..35.50 rows=1000 width=64)

예제로 살펴보기

필터가 적용된 간단한 쿼리를 살펴보겠습니다. 아래 실행 계획은 한 줄로 전체 상황을 보여 줍니다.

orders에 순차 스캔(테이블 전체 읽기)을 수행하고, status = 'shipped' 필터를 적용합니다. 플래너는 일치하는 행을 1000개로 예상합니다.

orders에 1천만 개의 행이 있고 그중 일치하는 행이 1000개뿐이라면, 면접관은 다음과 같이 답하기를 기대합니다: 여기서 순차 스캔은 비효율적이며, 상태 열에 인덱스를 만들거나 더 선택도가 높은 열에 인덱스를 만들면 테이블 전체를 읽지 않아도 됩니다.

EXPLAIN SELECT * FROM orders WHERE status = 'shipped';

Seq Scan on orders  (cost=0.00..18334.00 rows=1000 width=64)
  Filter: (status = 'shipped'::text)

예상 행 수와 실제 행 수

EXPLAIN ANALYZE를 사용하면 괄호 안에 실제 수치도 표시됩니다.

예를 보십시오. 플래너는 행을 1000개로 예상했지만, 실제로는 480000개를 가져왔습니다. 이는 480배 과소 추정한 것입니다. 플래너는 행이 적다고 가정하고 전략을 선택했으므로, 실제 데이터에 대해서는 그 선택이 잘못되었을 가능성이 큽니다.

면접에서는 이 차이를 핵심 진단으로 제시하십시오: 통계 정보가 오래되었으므로 테이블에서 ANALYZE를 실행하면 플래너가 더 나은 실행 계획을 선택할 가능성이 큽니다.

Seq Scan on orders
  (cost=0.00..18334.00 rows=1000 width=64)
  (actual time=0.02..210.4 rows=480000 loops=1)

loops=N의 의미

loops 값은 예상보다 훨씬 중요합니다. 이 값은 노드가 실행된 횟수입니다.

이 값은 중첩 루프 조인의 내부 쪽에 표시됩니다. 내부 노드는 바깥쪽 행마다 한 번씩 실행됩니다. loops=480000이라면 해당 내부 단계가 48만 번 실행된 것입니다.

중요한 점은 표시된 행별 시간과 행 수가 모두 루프당 값이라는 사실입니다. 실제 총합을 구하려면 여기에 loops를 곱해야 합니다. 루프당 0.004ms로 저렴해 보이는 노드도 480000번 반복되면 거의 2초가 됩니다.

Index Scan using idx_cust on orders
  (actual time=0.003..0.004 rows=1 loops=480000)

비용은 밀리초가 아니라 상대적 수치입니다

자주 발생하는 함정이 있습니다. 지원자가 cost=18334를 보고 18초가 걸립니다라고 말하는 경우입니다. 이는 잘못된 답입니다.

비용은 플래너의 임의 단위로 표시되며, 순차 페이지 읽기 한 번의 값이 1.0이 되도록 보정되어 있습니다. 비용은 실행 계획끼리 비교할 때만 의미가 있으며, 실제 경과 시간을 나타내는 수치가 아닙니다.

실제 시간을 확인하려면 EXPLAIN ANALYZE와 밀리초 단위로 측정된 actual time 값이 필요합니다. 면접에서 이를 명확히 말하십시오. 이 지표를 실제로 이해하고 있다는 것을 보여 줍니다.

조인 실행 계획 읽기

다음은 두 테이블을 사용하는 실행 계획입니다. 아래에서 위로 읽으십시오.

먼저 두 스캔이 orders와 customers에서 행을 수집합니다. 그런 다음 두 스캔의 결과가 해시 조인으로 전달됩니다. 한쪽은 해시 구조로 만들고 다른 쪽은 해시를 조회합니다. 조인의 결과는 다시 최종 결과로 전달됩니다.

들여쓰기가 구조를 보여 준다는 점에 주목하십시오. 두 스캔이 모두 해시 조인 아래에 있습니다. 면접관은 지원자가 조인 방식(여기서는 해시)과 어떤 테이블을 해시로 만들었는지(보통 더 작은 테이블)를 식별하기를 원합니다.

Hash Join  (cost=30.0..520.0 rows=900 width=72)
  Hash Cond: (o.customer_id = c.id)
  ->  Seq Scan on orders o  (cost=0..400 rows=10000)
  ->  Hash  (cost=18..18 rows=500)
        ->  Seq Scan on customers c  (cost=0..18 rows=500)

짚고 넘어가야 할 위험 신호

어떤 실행 계획에서든 다음과 같은 경고 신호를 빠르게 찾아낼 수 있도록 연습하십시오:

  • 대규모 테이블의 순차 스캔과 선택도가 높은 필터, 인덱스가 도움이 될 수 있습니다.
  • 예상 행 수와 실제 행 수의 큰 차이, 통계 정보가 오래되었을 가능성이 큽니다.
  • 큰 테이블에서 반복 횟수가 많은 중첩 루프, 내부 조인 키에 인덱스가 없는 경우가 많습니다.
  • 정렬 또는 해시가 디스크로 넘쳐나는 현상(Disk 사용량으로 표시됨), work_mem이 너무 작습니다.
  • 필터로 제거된 행 수가 매우 많음, 테이블 대부분을 읽은 뒤 버린 것입니다.

출력 형식과 BUFFERS

실행 계획은 여러 형식으로 제공됩니다. 기본 형식인 TEXT는 면접에서 소리 내어 읽게 되는 형식입니다. 하지만 구조화된 출력을 요청할 수도 있습니다.

EXPLAIN (FORMAT JSON) 또는 FORMAT YAML을 사용하면 도구와 대시보드가 구문 분석할 수 있는 기계 판독용 실행 계획이 생성됩니다. 직접 다룰 일은 드물지만, 이런 형식이 있다는 것을 아는 것은 숙련자다운 세심함입니다.

괄호 안에 옵션을 추가할 수 있습니다: EXPLAIN (ANALYZE, BUFFERS). BUFFERS 옵션은 캐시 적중과 디스크 읽기를 보고하므로, 입출력이 병목인 쿼리를 진단할 때 매우 유용합니다.

EXPLAIN (ANALYZE, BUFFERS)
SELECT * FROM orders WHERE customer_id = 42;

빠른 확인

면접관이 비용 부분에 rows=1000이 있지만 actual ... rows=480000도 표시된 EXPLAIN ANALYZE 노드를 보여 줍니다. 가장 가능성 높은 진단은 무엇입니까?

복습

이제 숙련자처럼 실행 계획을 읽을 수 있습니다:

  • EXPLAIN은 예상하고, EXPLAIN ANALYZE는 실행한 뒤 측정합니다.
  • 트리를 아래에서 위로 읽으십시오. 말단 노드가 먼저 실행되고 최상위 노드가 출력을 생성합니다.
  • 각 노드에는 비용(상대적 단위), 행 수, 너비가 표시되며, actual time이 실제 밀리초 수치입니다.
  • loops는 루프당 수치에 곱해지므로 중첩 루프를 주의하십시오.
  • 예상 행 수와 실제 행 수의 차이가 가장 중요한 진단 신호입니다.

실행 계획을 소리 내어 설명하고 위험 신호를 짚어 내는 것이 면접에서 좋은 평가를 받는 방식입니다.

자주 묻는 질문

“EXPLAIN 계획 읽기” 강의는 무료인가요?

네 — “EXPLAIN 계획 읽기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Coding Interview Prep 강의 전체를 잠금 해제할 수 있습니다. Coding Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.

“EXPLAIN 계획 읽기”에서 뭘 배우나요?

쿼리 계획에서 스캔 유형, 조인 방식, 비용 추정치를 해석합니다. 브라우저에서 직접 실행하는 실습 코드로 Coding Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Coding Interview Prep을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Coding Interview Prep은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 1번째 강의입니다.

“EXPLAIN 계획 읽기” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Coding Interview Prep 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Coding Interview Prep 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. EXPLAIN 계획 읽기
  2. 순차 스캔, 인덱스 스캔, 인덱스 전용 스캔 비교
  3. 조인 알고리즘: 중첩 루프, 해시, 병합
  4. 느린 쿼리 찾기와 수정
← Coding Interview Prep(으)로 돌아가기