DB/PostgreSQL

GPDB - Query Plan 예시

박쿠리 2024. 10. 1. 19:11

 

주문이 2024년 1월에 이루어지고 총 금액이 $100 이상인 고객의 이름과 해당 기간의 총 주문 금액을 계산하는 쿼리이다.

EXPLAIN ANALYZE
SELECT c.customer_name, SUM(oi.quantity * oi.price) AS total_amount
FROM customers c
JOIN orders o ON c.customer_id = o.customer_id
JOIN order_items oi ON o.order_id = oi.order_id
WHERE o.order_date BETWEEN '2024-01-01' AND '2024-01-31'
GROUP BY c.customer_name
HAVING SUM(oi.quantity * oi.price) >= 100;

 

GroupAggregate  (cost=XX..XX rows=XX width=XX) (actual time=XX..XX rows=1 loops=1)
  Group Key: c.customer_name
  Filter: (sum((oi.quantity * oi.price)) >= '100'::numeric)
  ->  Hash Join  (cost=XX..XX rows=XX width=XX) (actual time=XX..XX rows=6 loops=1)
        Hash Cond: (o.customer_id = c.customer_id)
        ->  Append  (cost=XX..XX rows=XX width=XX) (actual time=XX..XX rows=6 loops=1)
              ->  Seq Scan on orders_2024_01 o  (cost=XX..XX rows=XX width=XX) (actual time=XX..XX rows=3 loops=1)
              ->  Seq Scan on orders_2024_02 o  (cost=XX..XX rows=XX width=XX) (actual time=XX..XX rows=3 loops=1)
        ->  Hash  (cost=XX..XX rows=XX width=XX) (actual time=XX..XX rows=3 loops=1)
              Buckets: 1024  Batches: 1  Memory Usage: XXkB
              ->  Seq Scan on customers c  (cost=0.00..XX rows=XX width=XX) (actual time=XX..XX rows=3 loops=1)

 

 

Query plan 실행 흐름

*아래에서 위로 읽어야 한다.

 

  1. Seq Scan on customers c: customers 테이블을 순차적으로 스캔한다.
  2. Seq Scan on orders_2024_01 o: 파티션 테이블 orders의 해당 파티션(orders_2024_01)을 순차적으로 스캔한다. 이는 WHERE 조건의 order_date 범위로 인해 orders_2024_01만 선택적으로 스캔된다.
  3. Hash: customers 테이블의 결과를 해시 테이블로 메모리에 저장한다.
  4. Hash Join: orders와 customers의 조인 작업을 수행한다.
  5. GroupAggregate: 최종적으로 GROUP BY 절과 HAVING 조건을 적용하여 결과를 집계한다.

 

 

GroupAggregate

  • 설명: GROUP BY나 집계 함수(SUM, COUNT 등)를 처리할 때 사용된다.
  • Group Key: 쿼리에서 GROUP BY 절에 사용된 컬럼을 나타낸다.
  • Filter: HAVING 절의 조건을 처리한다.
  • cost=XX..XX:
    • cost=XX는 이 단계까지 예상되는 누적 비용의 시작 값이다.
    • cost=XX는 이 단계의 예상 종료 비용을 나타낸다.
  • actual time=XX..XX: 실제 실행 시간(시작부터 종료까지, 밀리초 단위)이다.
  • rows=XX: 이 단계에서 예상되는 결과 행의 수이다.
  • loops=XX: 이 단계가 몇 번 반복되었는지를 나타낸다.

Hash Join

  • 설명: 두 테이블을 조인할 때 사용하는 방식 중 하나입니다. 한 테이블의 데이터를 메모리에 해시 테이블로 저장한 후, 다른 테이블의 행을 이 해시 테이블과 비교하여 매칭한다.
  • Hash Cond: 조인에 사용되는 조건을 나타낸다.
  • cost=XX..XX, actual time=XX..XX 등의 의미는 위와 동일하다.

Append

  • 설명: 파티션 테이블의 경우 여러 파티션을 결합할 때 사용된다. 단일 테이블이 아니라 여러 파티션을 결합해야 하는 경우 나타난다.
  • 이 단계에서 orders_2024_01 파티션만 선택적으로 스캔하는 모습을 볼 수 있다.

Seq Scan (Sequential Scan)

  • 설명: 테이블의 모든 행을 순차적으로 스캔하는 방법이다. 인덱스가 없거나 쿼리가 테이블의 모든 행을 필요로 하는 경우 나타난다.
  • 주의점: 대량의 데이터에서 Seq Scan이 자주 발생하면 성능 저하의 원인이 될 수 있다. 인덱스 생성으로 Seq Scan을 Index Scan으로 변경할 수 있다.
  • Hash Join, Merge Join, Nested Loop Join 중 상황에 맞는 조인 전략을 사용해야 한다. 인덱스가 있는 경우 Merge Join이 더 효율적일 수 있다.

Hash

  • 설명: Hash Join을 수행하기 위해 한 테이블의 데이터를 메모리에 해시 테이블로 만드는 단계이다.
  • Buckets: 해시 테이블에 사용된 버킷 수를 나타낸다.
  • Batches: 버킷을 얼마나 많이 배치하여 처리했는지를 나타낸다.
  • Memory Usage: 이 해시 작업에 사용된 메모리 양을 나타낸다.

 

반응형

'DB > PostgreSQL' 카테고리의 다른 글

could not find segment file  (0) 2025.01.22
cgroup  (0) 2024.11.18
GPDB - motion 정의  (0) 2024.09.12
GPDB 분산키 Randomly vs 특정 컬럼  (0) 2024.09.12
PostgreSQL 로그인 권한 - 연결 실패  (0) 2024.08.31