PostgreSQL:Explain
쿼리의 성능을 측정(EXPLAIN) 한다.
모든 쿼리 앞에 EXPLAIN ANALYZE
를 붙이면 된다.
Cost
EXPLAIN을 쓰면 알아서 사용되는 옵션입니다. 단계별 실행 계획에서 예측된 시작 비용과 총 비용을 보여주며, 로우의 예측된 수과 한 로우의 크기(예측값)도 보여줍니다.
COST 계산은 TIME BASE 입니다. COST 를 산정하는 계산식이 존재하며, 대소에 영향을 주는 인자들이 존재합니다. 이 인자값은 시스템, 세션 레벨에서 변경 가능하며, 그 결과로 실행플랜이 변경 됩니다. 예를 들면 Sequential read 가 발생하는 경우 cost 의 계산식은 다음과 같습니다:
위에서 시스템 파라미터는 seq_page_cost, cpu_tuple_cost 이렇게 두 개이며 그 default 값은 다음과 같습니다:
- seq_page_cost = 1
- cpu_tuple_cost = 0.01
때문에 disk pages 23 개로 구성 되어있고, rows 가 5,000 개인 테이블은 그 코스트가 73 이 됩니다.
FORMAT
출력 양식을 지정하여 보기 좋게 만들어주는 옵션입니다. 설정 가능한 양식은 TEXT, XML, JSON, YAML 등이 있습니다. 아래와 같이 양식을 지정해줄 수 있습니다.
Postgresql 9.x 이후의 버전에서 사용가능합니다.
TIMING
단계별 실행 계획에서 실제 시작시간과 총 소요된 시간을 보여줍니다. 이 옵션은 실제 소요된 데이터를 보여주기 ANALYZE 옵션과 같이 사용해야만 기능이 동작됩니다.
Example
EXPLAIN ANALYZE
WITH d AS (
SELECT
DISTINCT ad.a4y_uid AS device_uid,
ad.name AS device_name,
ad.description AS device_description,
ad.chart_color AS chart_color,
COUNT(s.time) OVER(PARTITION BY s.a4y_uid) AS service_count,
MAX(s.time) OVER(PARTITION BY s.a4y_uid) AS service_last_time
FROM a4y_device ad
LEFT JOIN a4y_service s ON s.a4y_uid=ad.a4y_uid
WHERE ad.group_slug='aa' AND ad.project_slug='aa'
)
SELECT
d.device_name,
d.device_description,
d.chart_color,
d.service_count,
d.service_last_time,
asl.*
FROM d
LEFT JOIN a4y_state_last asl ON asl.uid=d.device_uid;
결과 화면:
Hash Right Join (cost=24.09..25.14 rows=1 width=438) (actual time=0.224..0.237 rows=2 loops=1)
Hash Cond: (asl.uid = d.device_uid)
-> Seq Scan on a4y_state_last asl (cost=0.00..1.03 rows=3 width=76) (actual time=0.006..0.007 rows=3 loops=1)
-> Hash (cost=24.07..24.07 rows=1 width=366) (actual time=0.195..0.198 rows=2 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 9kB
-> Subquery Scan on d (cost=24.04..24.07 rows=1 width=366) (actual time=0.181..0.190 rows=2 loops=1)
-> Unique (cost=24.04..24.06 rows=1 width=370) (actual time=0.178..0.187 rows=2 loops=1)
-> Sort (cost=24.04..24.05 rows=1 width=370) (actual time=0.177..0.181 rows=4 loops=1)
Sort Key: ad.a4y_uid, ad.name, ad.description, ad.chart_color, (count(s."time") OVER (?)), (max(s."time") OVER (?))
Sort Method: quicksort Memory: 25kB
-> WindowAgg (cost=24.01..24.03 rows=1 width=370) (actual time=0.103..0.150 rows=4 loops=1)
-> Sort (cost=24.01..24.02 rows=1 width=362) (actual time=0.079..0.082 rows=4 loops=1)
Sort Key: s.a4y_uid
Sort Method: quicksort Memory: 25kB
-> Hash Right Join (cost=11.21..24.00 rows=1 width=362) (actual time=0.056..0.069 rows=4 loops=1)
Hash Cond: (s.a4y_uid = ad.a4y_uid)
-> Seq Scan on a4y_service s (cost=0.00..12.20 rows=220 width=12) (actual time=0.010..0.011 rows=5 loops=1)
-> Hash (cost=11.20..11.20 rows=1 width=350) (actual time=0.033..0.034 rows=2 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 9kB
-> Seq Scan on a4y_device ad (cost=0.00..11.20 rows=1 width=350) (actual time=0.019..0.021 rows=2 loops=1)
Filter: (((group_slug)::text = 'aa'::text) AND ((project_slug)::text = 'aa'::text))
Rows Removed by Filter: 1
Planning Time: 0.594 ms
Execution Time: 0.486 ms