うまいぼうぶろぐ

linuxとhttpdとperlのメモ

postgresql の EXPLAIN


EXPLAINとEXPLAIN ANALYZEがある。

EXPLAIN

データベースエンジンが行おうとしている処理の実行計画を表示

EXPLAIN ANALYZE

EXPLAINの実行計画に基づいて"実行した"実行結果を表示する。実際に実行するので、insert/updateなどのクエリだと、中身を更新してしまうので注意。
影響を与えないようにするにはtransactionを使ってrollbackさせる。

BEGIN;
EXPLAIN ANALYZE "何かのSQL";
ROLLBACK;

見方

idというcolumnだけを持ったtableで実験。

> \d test_table
  Table "public.test_table"
 Column |  Type   | Modifiers 
--------+---------+-----------
 id     | integer | not null
Indexes:
	"test_table_pkey" PRIMARY KEY, btree (id)

EXPLAIN

> EXPLAIN select * from test_table where id = 100;
                 QUERY PLAN                                    
--------------------------------------------------
 Index Scan using test_table_pkey on test_table  (cost=0.00..8.27 rows=1 width=4)
   Index Cond: (id = 100)
(2 rows)
  • Index Scan using test_table_pkey on test_table

test_table中のtest_table_pkeyからindexを検索した

  • (cost=0.00..8.27 rows=1 width=4)

costはオプティマイザが推測した実行時間
rowsは返却されるレコード数。この値が実際のレコード数と大きく異なる場合はanalyze が必要らしい。

  • Index Cond: (id = 100)

indexの条件は id = 100;

EXPLAIN ANALYZE

> EXPLAIN ANALYZE select * from test_table where id = 100;
		      QUERY PLAN                                                         
---------------------------------------------------------
 Index Scan using test_table_pkey on test_table  (cost=0.00..8.27 rows=1 width=4) (actual time=0.018..0.021 rows=1 loops=1)
   Index Cond: (id = 100)
 Total runtime: 0.052 ms
(3 rows)
  • (actual time=0.018..0.021 rows=1 loops=1)

実際にかかったSQL実行、結果の取得にかかった時間

想定以上にSQL実行時間がかかっている場合はたいていindex張り忘れとか、SQLの書き方が悪くてindexを使えていないとか。その場合はIndex Scan usingにならずに、Seq Scanとかになる。