Skip to content

PostgreSQL:Explain

쿼리의 성능을 측정(EXPLAIN) 한다.

모든 쿼리 앞에 EXPLAIN ANALYZE를 붙이면 된다.

Cost

EXPLAIN을 쓰면 알아서 사용되는 옵션입니다. 단계별 실행 계획에서 예측된 시작 비용과 총 비용을 보여주며, 로우의 예측된 수과 한 로우의 크기(예측값)도 보여줍니다.

COST 계산은 TIME BASE 입니다. COST 를 산정하는 계산식이 존재하며, 대소에 영향을 주는 인자들이 존재합니다. 이 인자값은 시스템, 세션 레벨에서 변경 가능하며, 그 결과로 실행플랜이 변경 됩니다. 예를 들면 Sequential read 가 발생하는 경우 cost 의 계산식은 다음과 같습니다:

(disk pages read * seq_page_cost) + (rows scanned * cpu_tuple_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 이후의 버전에서 사용가능합니다.

EXPLAIN (FORMAT YAML)
SELECT * FROM t_sport WHERE teem_name = 'fc_seoul';

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

See also

Favorite site