주문이 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 실행 흐름
*아래에서 위로 읽어야 한다.
- Seq Scan on customers c: customers 테이블을 순차적으로 스캔한다.
- Seq Scan on orders_2024_01 o: 파티션 테이블 orders의 해당 파티션(orders_2024_01)을 순차적으로 스캔한다. 이는 WHERE 조건의 order_date 범위로 인해 orders_2024_01만 선택적으로 스캔된다.
- Hash: customers 테이블의 결과를 해시 테이블로 메모리에 저장한다.
- Hash Join: orders와 customers의 조인 작업을 수행한다.
- 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 |