PostgreSQLスキルアップノート(自己啓発のための個人サイト)
実行計画を制御・プランナメソッド設定編
【一覧に戻る】
マニュアルへのリンクは/9.2/としています。
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
■■■■ PostgreSQL スキルアップノート
■■■■
■◆■■ 実行計画を制御・プランナメソッド設定編
■■■■
■■■■
■■■■ 使用環境:PostgreSQL9.1.7 (CentOS6.2)
2013/02/18
2013/03/15
(C) 2013 ohdb
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
プランナメソッド設定により実行計画を制御する方法。
【マニュアル】
第18章サーバの設定− 問い合わせ計画−プランナメソッド設定
→●[マニュアル]
第18章サーバの設定− 問い合わせ計画−プランナコスト定数
→●[マニュアル]
第14章性能に関するヒント・明示的なJOIN句でプランナを制御する
→●[マニュアル]
■1■ 概要
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
set enable_nestloop = off;
のように、セッションの中で、特定の実行計画を採用させない指定をして実行計画を制御する。
指定できるのは以下の通り(9.2)
・デフォルトはすべてonなので、禁止させたいときにoff指定する。
・△印はoffにしても完全な禁止にはならない。
スキャン系
-------------------------------------------------------------------------------
enable_seqscan △ シーケンシャル走査計画
enable_indexscan インデックス走査計画型
enable_bitmapscan ビットマップ走査計画型 ビットマップスキャン
enable_indexonlyscan インデックス走査計画型のみ※1 インデックスオンリースキャン
enable_tidscan TID走査計画型 TIDスキャン
結合系
-------------------------------------------------------------------------------
enable_nestloop △ 入れ子になったループ結合計画 ネステッドループ
enable_mergejoin マージ結合計画型
enable_hashjoin ハッシュ結合計画型
集約・ソートその他
-------------------------------------------------------------------------------
enable_hashagg ハッシュ集約計画型 ※1
enable_sort △ 明示的並び替え手順(ソート)
enable_material △ 具体化の使用
第18章サーバの設定− 問い合わせ計画−プランナメソッド設定
→●[マニュアル]
2013/03/20現在 9.2マニュアル誤記等
※1「インデックス走査計画型のみ」ではなく「インデックスのみ走査計画型」?
どちらにしても日本語の説明にしない方が分かりやすい。
※2 enable_hashaggの説明がenable_hashjoinと同じになってしまっている。
■2■ 準備
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
【□】 テーブルt1(20件),t2(100万件)作成
┌────────────────────────────┐
DROP TABLE if exists t1,t2;
CREATE TABLE t1 (c1 int PRIMARY KEY,c2 int);
CREATE TABLE t2 (c1 int PRIMARY KEY,c2 timestamp,c3 int);
WITH RECURSIVE tmp(c1,c2) AS (
SELECT 1,floor(random()*20) UNION ALL
SELECT c1+1,floor(random()*20) FROM tmp WHERE c1 < 20
)INSERT INTO t1 SELECT * FROM tmp;
--
WITH RECURSIVE tmp(c1,c2,c3) AS (
SELECT 1, current_timestamp,floor(random()*1000000) UNION ALL
SELECT c1+1, c2 + '1 hours' ,floor(random()*1000000) FROM tmp WHERE c1 < 1000000
)INSERT INTO t2 SELECT * FROM tmp;
VACUUM ANALYZE t1;
VACUUM ANALYZE t2;
-- t1とt2の定義と件数を確認
\d t[12];
SELECT COUNT(*) FROM t1;
SELECT COUNT(*) FROM t2;
--
-- EXPLAIN準備
\set ep1 'EXPLAIN (ANALYZE,VERBOSE,BUFFERS)'
\set ep2 'EXPLAIN ANALYZE'
└────────────────────────────┘
実行計画の確認は、以降では
:ep1 SQL文; あるいは
:ep2 SQL文;
のようにして確認することができる。
EXPLAIN (ANALYZE,VERBOSE,BUFFERS) などの記法は、バッファなどより詳細な情報を
取得する指定でカッコとともに使う。(9.0以降の比較的新しい構文)
■3■ プランナメソッド設定による実行計画の制御
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
改めて接続しなおした場合のみ以下を実行する。
\set ep1 'EXPLAIN (ANALYZE,VERBOSE,BUFFERS)'
\set ep2 'EXPLAIN ANALYZE'
1.プランナメソッド設定なしでそのまま実行
──────────────────────────────
【□】
┌────────────────────────────┐
:ep1 select * from t2 where c1<1000000;
└────────────────────────────┘
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
Seq Scan on public.t2 (cost=0.00..18870.00 rows=1000000 width=16) (actual time=0.031..320.899 rows=999999 loops=1)
Output: c1, c2, c3
Filter: (t2.c1 < 1000000)
Rows Removed by Filter: 1
Buffers: shared hit=2874 read=3496
Total runtime: 520.082 ms
・・・・絞り込みが非常に緩いので、シーケンススキャンが採用された。
2.設定を入れて実行
──────────────────────────────
【□】 以下のようにスキャン系の設定のうち、インデックスのみをon
┌────────────────────────────┐
set enable_seqscan = off;
set enable_indexscan = on;
set enable_bitmapscan = off;
set enable_indexonlyscan = off;
:ep1 select * from t2 where c1<1000000;
└────────────────────────────┘
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------
Index Scan using t2_pkey on public.t2 (cost=0.00..34853.36 rows=1000000 width=16) (actual time=0.055..396.595 rows=999999 loops=1)
Output: c1, c2, c3
Index Cond: (t2.c1 < 1000000)
Buffers: shared hit=1 read=9104
Total runtime: 600.702 ms
・・・・設定によってインデックススキャンに変わった。
以降未整備
以上