Skip to main content
Copyright © 2013 NTT DATA Corporation 
2013年2月16日 NTTデータ 基盤システム事業本部 
使ってみませんか? pg_hint_plan 
PostgreSQLアンカンファレンス@東京 
第25回しくみ+アプリケーション勉強会
2 
Copyright © 2013 NTT DATA Corporation 
目次 
pg_hint_planの紹介 
デモ 
HINT句とコミュニティ 
HINT句とNTTデータ
Copyright © 2013 NTT DATA Corporation 
3 
pg_hint_planの紹介
4 
Copyright © 2013 NTT DATA Corporation 
pg_hint_planとは? 
PostgreSQLでHINT句を使えるようにする外部モジュール 
開発元 
NTT OSSセンタ 
公開日 
2012年12月 
ライセンス 
BSD 
対応バージョン 
PostgreSQL9.1、9.2 
公開先 
http://en.sourceforge.jp/projects/pghintplan/ 
pg_hint_plan
5 
Copyright © 2013 NTT DATA Corporation 
統計 情報 
プランとは? 
シーケンシャルスキャン 
インデックススキャン 
インデックスオンリースキャン 
SQLの実行方法にも複数ある 
PostgreSQLは、統計情報から最適な方法を選択してSQL実行 
プランとは、SQLを実行する方法のこと 
どのようにSQL を実行するのが 最適だろう?
6 
Copyright © 2013 NTT DATA Corporation 
プラン選択の課題 
どのプランを選ぶかはPostgreSQL任せ 
PostgreSQLが最適なプランを選んでくれなくて性能劣化 
DBの状況変化に伴い、突然不適切なプランが選ばれて性能劣化 
商用DBは、プラン選択をDB任せにせず、ユーザに制御させる機能を提供 
PostgreSQLではGUCパラメータである程度制御可能だが、柔軟でない 
柔軟なプラン制御を外部ツールで実現 
HINT句 
統計情報 
の固定化 
DBに指示(HINT)を与えて、どのプランを選ぶかユーザ が思い通りに制御 → pg_hint_plan 
一度最適なプランを選んだら、ずっとそのプランを選ぶ ように統計情報を固定化 → pg_dbms_stats
7 
Copyright © 2013 NTT DATA Corporation 
統計 情報 
HINT句のイメージ 
シーケンシャルスキャン 
インデックススキャン 
インデックスオンリースキャン 
インデックススキャンを 選ぶように! 
HINT 
選択
8 
Copyright © 2013 NTT DATA Corporation 
pg_hint_planでのHINT句の指定 
HINT句は、クエリ先頭のブロックコメント /*+ ... */ 内に指定 
クエリ先頭以外の/*+ */は、HINT句と見なされない 
商用DBとはHINT句の指定場所が異なるため注意 
/*+ 
SeqScan(t1) 
IndexScan(t2 t2_pkey) 
*/ 
SELECT /*+ IndexScan(t1 t1_pkey) */ 
* FROM table1 t1 JOIN table2 t2 ON (t1.key = t2.key); 
table1はシーケンシャルスキャン、 table2は主キーインデックスt2_pleyの 
インデックスキャンを指示するHINT句 
クエリ先頭以外の HINT句は無視される
9 
Copyright © 2013 NTT DATA Corporation 
pg_hint_planがサポートするHINT句の種類 
商用DBで特に使われるHINT句をサポート 
カテゴリ 
説明 
スキャン方法 
テーブルをどの方法でスキャンするか? 
結合方法 
テーブルをどの方法で結合するか? 
結合順序 
テーブルをどの順序で結合するか? 
パラメータ設定 
プラン作成中だけ使うパラメータ設定
10 
Copyright © 2013 NTT DATA Corporation 
pg_hint_planがサポートするHINT句の種類 
スキャン方法のHINT句 
書式 
説明 
SeqScan 
シーケンシャルスキャンを選択 
TidScan 
TIDスキャンを選択 
IndexScan 
インデックススキャンを選択 
スキャンにどのインデックスを使うか指定可能 
IndexOnlyScan 
インデックスオンリースキャンを選択(PostgreSQL9.2以降) 
スキャンにどのインデックスを使うか指定可能 
BitmapScan 
ビットマップスキャンを選択 
スキャンにどのインデックスを使うか指定可能
11 
Copyright © 2013 NTT DATA Corporation 
pg_hint_planがサポートするHINT句の種類 
スキャン方法のHINT句 
書式 
説明 
NoSeqScan 
シーケンシャルスキャン以外で最小コストのスキャンを選択 
NoTidScan 
TIDスキャン以外で最小コストのスキャンを選択 
NoIndexScan 
インデックススキャン以外で最小コストのスキャンを選択 
NoIndexOnlyScan 
インデックスオンリースキャン以外で最小コストのスキャンを選択 
(PostgreSQL9.2以降) 
NoBitmapScan 
ビットマップスキャン以外で最小コストのスキャンを選択
12 
Copyright © 2013 NTT DATA Corporation 
pg_hint_planがサポートするHINT句の種類 
結合方法のHINT句 
書式 
説明 
NestLoop 
ネストループ結合を選択 
HashJoin 
ハッシュ結合を選択 
MergeJoin 
マージ結合を選択 
NoNestLoop 
ネストループ結合以外で最小コストの結合を選択 
NoHashJoin 
ハッシュ結合以外で最小コストの結合を選択 
NoMergeJoin 
マージ結合以外で最小コストの結合を選択
13 
Copyright © 2013 NTT DATA Corporation 
pg_hint_planがサポートするHINT句の種類 
結合順序のHINT句 
パラメータ設定のHINT句 
書式 
説明 
Leading 
テーブルを指定した通りの順番で結合 
書式 
説明 
Set 
プラン作成中だけGUCパラメータを指定した値に変更
Copyright © 2013 NTT DATA Corporation 
14 
デモ
15 
Copyright © 2013 NTT DATA Corporation 
インストールと設定 
インストールはいつものやり方 
$ tar zxf pg_hint_plan92-1.0.0.tar.gz 
$ cd pg_hint_plan92-1.0.0 
$ make ※USE_PGXS=1を未指定でも自動的にpgxsを使ってビルド 
$ su 
# make install 
PostgreSQLがpg_hint_planをロードするようにパラメータ設定 
$ vi $PGDATA/postgresql.conf 
shared_preload_libraries = 'pg_hint_plan' 
※custom_variable_classesはv9.2以降廃止されたため、設定不要
16 
Copyright © 2013 NTT DATA Corporation 
HINT句お試し 
単純なSQLでHINT句を使用 
=# CREATE TABLE hoge (a int, b int); 
=# INSERT INTO hoge SELECT x, x FROM generate_series(1,10000) x; 
=# CREATE INDEX aaa_idx ON hoge (a); 
=# CREATE INDEX bbb_idx ON hoge (b); 
=# VACUUM ANALYZE hoge; 
=# EXPLAIN ANALYZE 
SELECT * FROM hoge WHERE a < 9000 AND b > 10; 
/*+ BitmapScan(hoge) */ 
/*+ SeqScan(hoge) */ 
/*+ IndexScan(hoge aaa_idx) */ 
/*+ IndexScan(hoge bbb_idx) */
17 
Copyright © 2013 NTT DATA Corporation 
HINT句お試し 
複雑なSQLでHINT句を使用 
不適切なプランが選ばれた例としてコミュニティで報告されていたものをデモ用 に変更 
http://www.postgresql.org/message-id/E1TSyAf-0006st- DI@wrigleys.postgresql.org 
=# CREATE TABLE goods (id text primary key, price int, num int); 
=# (10万件のデータ挿入) 
=# CREATE INDEX goods_price_idx ON goods(price); 
=# VACUUM ANALYZE goods; 
ID、値段、個数の3列を持つ商品テーブルをイメージ 
id列は、ランダムな英数字10文字 
price列は、0~10万のランダムな数字 
num列は、0~10のランダムな数字 or NULL
18 
Copyright © 2013 NTT DATA Corporation 
HINT句お試し 
複雑なSQLでHINT句を使用 
/*+ HashJoin(goods ANY_subquery) */ 
EXPLAIN ANALYZE 
SELECT 
* 
FROM 
goods 
WHERE 
id IN ( SELECT id FROM goods ORDER BY price LIMIT 605 ) 
AND 
num IS NULL 
ORDER BY 
price DESC 
LIMIT 1; 
値段が安い商品605件のうち 
在庫がない(個数がNULLである)商品で 
最も値段が高い商品を 
1件だけ検索する 
HINT句未指定だと、プランナが不適切なプランを選択して、 低性能 
現状プランナのよい改善案はなく、WITH句を使ったSQLに 書き換えることで問題を回避する必要がある
19 
Copyright © 2013 NTT DATA Corporation 
pg_hint_planの制約 
HINT句で制御できないケース 
HINT句で選択できるプランは、プランナが選択候補として挙げられるプランのみ 
インデックス未定義の場合、インデックススキャンを選択できない 
FULL OUTER JOINでは、ネストループ結合は選択できない 
PL/pgSQLにおける制限 
PL/pgSQL関数内のクエリに直接HINT句を指定しても無視される 
関数実行時のSELECTにHINT句を指定すること 
ただし、関数内のクエリがそのまま実行されるとは限らないため、HINT句が期待どお り動作するかは保証外 
ドキュメントに、制約が詳細に列挙されているため、 
pg_hint_plan利用時には読んでおくこと!
Copyright © 2013 NTT DATA Corporation 
20 
HINT句とコミュニティ
21 
Copyright © 2013 NTT DATA Corporation 
HINT句とPostgreSQLコミュニティ 
http://wiki.postgresql.org/wiki/OptimizerHintsDiscussion
22 
Copyright © 2013 NTT DATA Corporation 
HINT句に対するコミュニティのスタンス 
PostgreSQLがHINT句をサポートすることを、長年多くの人々が望んできた が、コミュニティの現在の公式なスタンスは、 
他DBと同じやり方でHINT句を実装することに興味がない 
「他DBにはあるから、PostgreSQLにもあるべき」という提案は歓迎しな い 
他DBのHINT句には問題がある。問題を改善するアイデアがあるなら、 価値ある議論ができるかも
23 
Copyright © 2013 NTT DATA Corporation 
コミュニティが考えるHINT句の問題 
アプリケーションのコードがメンテナンスしにくくなる。クエリに指定され たHINT句は、多大なリファクタリングを必要とする 
アップグレードを邪魔する。今日役立ってるHINT句は、アップグレード後 に性能劣化の原因になるかもしれない 
DBAが、真の問題を解決する代わりに、HINT句に頼り切ってしまう。こ の悪い癖をHINT句は助長する 
HINT句はデータサイズに対してスケールしない。テーブルが小さいとき に正しかったHINTは、大きくなったときに間違ってしまう 
PostgreSQLのプランナの改善を邪魔する。HINT句の利用者は、クエリ の問題をコミュニティに報告しなくなる
24 
Copyright © 2013 NTT DATA Corporation 
コミュニティが考えるHINT句の使いどころ 
メンテナンス性を気にする必要のない単発クエリ 
様々なプランをテストして、プランナがどう動くのか見るための方法 
プランナのバグの対策 
既知の実装上のバグ 
理論上の問題。プラン見積もりの上限など
Copyright © 2013 NTT DATA Corporation 
25 
HINT句とNTTデータ
26 
Copyright © 2013 NTT DATA Corporation 
NTTデータがHINT句を必要とする理由 
性能の安定化 
基幹系システムでは、最高性能より性能の安定性の方が重要 
プランが変化することによる突然の性能向上/劣化を避けたい 
HINT句でプランを固定化し、性能を安定化させたい! 
クエリチューニングの(最終)手段 
どう頑張っても最適なプランを選んでくれないクエリのチューニング 
プランナのバグは修正済だが、マイナーバージョンのリリースまで時間が あり、システム開発に間に合わない場合のチューニング 
商用DBからPostgreSQLへのマイグレーションの促進 
HINT句のリスクは承知済。リスクのシステムへの影響を見切った上で利用
Copyright © 2013 NTT DATA Corporation 
27 
まとめ
28 
Copyright © 2013 NTT DATA Corporation 
まとめ 
HINT句は使い方次第で 
魔法の杖にも 
トラブルの元凶にもなります。 
効果とリスクを正しく理解し、 
pg_hint_planで 
PostgreSQLの一歩進んだ使い方を!
Copyright © 2011 NTT DATA Corporation 
Copyright © 2013 NTT DATA Corporation