1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD html 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
4 <title>pg_hint_plan</title>
5 <!-- Uncoment after the tool has been hosted somewhere.
6 <link rel="home" title="pg_hint_plan" href="index.html">
8 <link rel="stylesheet" type="text/css" href="style.css">
9 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
13 <h1 id="pg_hint_plan">pg_hint_plan 0.1.0</h1>
14 <div class="navigation">
15 <a href="pg_hint_plan-ja.html">pg_hint_plan</a>
21 <li><a href="#name">pg_hint_planとは?</a></li>
22 <li><a href="#description">機能概要</a></li>
23 <li><a href="#install">インストール</a>
25 <li><a href="#requirement">動作環境</a></li>
26 <li><a href="#build">ビルド</a></li>
29 <li><a href="#uninstall">アンインストール</a></li>
30 <li><a href="#usage">使い方</a>
32 <li><a href="#hint-load">pg_hint_planのロード</a></li>
33 <li><a href="#hint-rule">ヒントの記述方法</a></li>
34 <li><a href="#hint-type">ヒントのグループ</a></li>
35 <li><a href="#hint-GUC">pg_hint_planのGUCパラメータ</a></li>
38 <li><a href="#restrictions">使用上の注意と制約</a></li>
39 <li><a href="#known-issues">既知の問題</a></li>
40 <li><a href="#seealso">関連項目</a></li>
43 <h2 id="name">pg_hint_planとは?</h2>
44 <p>pg_hint_planは、元のSQL文を変えずに実行計画を制御するためのツールです。</p>
46 <h2 id="description">機能概要</h2>
47 <p>pg_hint_planを用いると、ヒントを記述したブロックコメントをSQL文の前に加えることで、実行計画を制御することができます。</p>
49 <h2 id="install">インストール</h2>
50 <p>pg_hint_planのインストール方法について説明します。</p>
52 <h3 id="requirement">動作環境</h3>
56 <dd>バージョン 9.2devel 4月2日版</dd>
57 <dt>動作検証済みOS</dt><dd>RHEL 6.1</dd>
60 <h3 id="build">ビルド</h3>
61 <p>pg_hint_planをソースコードからビルドする場合、pg_hint_planのソースを展開したディレクトリでmake → make installの順に実行してください。なお、pg_hint_planのビルドにはpgxsを使用するので、RPM版のPostgreSQLを使用している環境では、postgresql-devel パッケージが必要です。</p>
64 $ tar xzvf pg_hint_plan-0.1.0.tar.gz
65 $ cd pg_hint_plan-0.1.0
70 <h2 id="uninstall">アンインストール</h2>
71 <p>pg_hint_planをアンインストールするには、pg_hint_planのソースを展開したディレクトリでmake uninstallを実行してください。</p>
72 <p>以下にアンインストールの例を示します。</p>
74 $ cd pg_hint_plan-0.1.0
78 <h2 id="usage">使い方</h2>
79 <p>pg_hint_planの使い方について説明します。</p>
81 <h3 id="hint-load">pg_hint_planのロード</h3>
82 <p>pg_hint_planを使うには、以下の例のようにpg_hint_planの共有ライブラリをロードしてください。全てのセッションでpg_hint_planを有効にするには、shared_preload_librariesに'pg_hint_plan'を追加して下さい。</p>
84 postgres=# LOAD 'pg_hint_plan';
88 <h3 id="hint-rule">ヒントの記述方法</h3>
89 <p>ヒントはクエリの前のブロックコメント内に、スペース、タブまたは改行のいずれかで区切って記述してください。ヒントの対象がテーブルの場合は、テーブル名または別名(エイリアス)で指定してください。ただし、スキーマが異なる同じ名前のテーブルを1クエリ中に用いる場合は、別名で指定してください。これは、クエリ中の特定のテーブルを指定できるようにするためです。</p>
91 <p>以下の例では、HashJoinとSeqScanヒントにより、pgbench_accountsテーブルに対するSeq Scanの結果をHash Joinする実行計画が選択されています。</p>
94 postgres*# <span class="strong">HashJoin(a b)</span>
95 postgres*# <span class="strong">SeqScan(a)</span>
97 postgres-# EXPLAIN SELECT *
98 postgres-# FROM pgbench_branches b
99 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid
100 postgres-# ORDER BY a.aid;
102 ---------------------------------------------------------------------------------------
103 Sort (cost=31465.84..31715.84 rows=100000 width=197)
105 -> <span class="strong">Hash Join</span> (cost=1.02..4016.02 rows=100000 width=197)
106 Hash Cond: (a.bid = b.bid)
107 -> <span class="strong">Seq Scan on pgbench_accounts a</span> (cost=0.00..2640.00 rows=100000 width=97)
108 -> Hash (cost=1.01..1.01 rows=1 width=100)
109 -> Seq Scan on pgbench_branches b (cost=0.00..1.01 rows=1 width=100)
114 <h3 id="hint-type">ヒントのグループ</h3>
115 <p>pg_hint_planで使えるヒントのグループは、スキャン方式と結合方式、結合順序、GUCパラメータの4通りに分けられます。同じグループのヒントを同じオブジェクトに対して指定した場合は、最後に指定したヒントが適用されます。各グループの具体的なヒントは、<a href="hint_list-ja.html">ヒント一覧</a>を参照してください。</p>
118 <p>テーブルに対して、どんなスキャンを選択するか指定できるヒントのグループのことです。
119 特定のテーブルに対するスキャン方式を選択したい場合は、そのスキャン方式のヒントと、対象となるオブジェクトの名前を指定してください。
120 特定のテーブルに対するスキャン方式を選択してほしくない場合は、そのスキャン方式のヒントの先頭に No を記述した上で、対象となるオブジェクトの名前を指定してください。</p>
121 <p>以下に示した具体例について説明します。</br>
122 1つ目のSQL文では、aテーブルにIndex Scanを選択させるヒントを用いたため、実行計画作成時にaテーブルに対してIndex Scanを選択しています。</br>
123 2つ目のSQL文では、aテーブルにIndex Scan以外を選択させるヒントを用いたため、実行計画作成時にaテーブルに対してIndex Scan以外のスキャン方式であるSeq Scanを選択しています。</p>
124 <pre>postgres=# /* <span class="strong">IndexScan(a)</span> */
125 postgres-# EXPLAIN SELECT *
126 postgres-# FROM pgbench_accounts a
127 postgres-# ORDER BY aid;
129 ---------------------------------------------------------------------------------------------------------
130 <span class="strong">Index Scan</span> using pgbench_accounts_pkey on pgbench_accounts a (cost=0.00..4247.26 rows=100000 width=97)
133 postgres=# /* <span class="strong">NoIndexScan(a)</span> */
134 postgres-# EXPLAIN SELECT *
135 postgres-# FROM pgbench_accounts a
136 postgres-# ORDER BY aid;
138 ---------------------------------------------------------------------------------
139 Sort (cost=21885.82..22135.82 rows=100000 width=97)
141 -> <span class="strong">Seq Scan</span> on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
147 <p>テーブルの結合に対して、どんな結合を選択するか指定できるヒントのグループのことです。
148 特定の結合方式を選択したい場合は、その結合方式のヒントと、対象となる2つ以上のオブジェクトの名前を指定してください。
149 特定の結合方式を選択してほしくない場合は、その結合方式のヒントの先頭に No を記述した上で、対象となるオブジェクトの名前を指定してください。</p>
150 <p>以下に示した具体例について説明します。</br>
151 1つ目のSQL文では、aテーブルとbテーブルの結合にMerge Joinを選択させるヒントを用いたため、実行計画作成時にMerge Joinを選択しています。</br>
152 2つ目のSQL文では、aテーブルとbテーブルの結合にMerge Join以外を選択させるヒントを用いたため、実行計画作成時にMerge Join以外の結合方式であるNested Loopを選択しています。</p>
155 postgres*# <span class="strong">MergeJoin(b a)</span>
157 postgres-# EXPLAIN SELECT *
158 postgres-# FROM pgbench_branches b
159 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid;
161 ---------------------------------------------------------------------------------------------
162 <span class="strong">Merge Join</span> (cost=21886.84..23636.85 rows=100000 width=197)
163 Merge Cond: (b.bid = a.bid)
164 -> Sort (cost=1.02..1.02 rows=1 width=100)
166 -> Seq Scan on pgbench_branches b (cost=0.00..1.01 rows=1 width=100)
167 -> Materialize (cost=21885.82..22385.82 rows=100000 width=97)
168 -> Sort (cost=21885.82..22135.82 rows=100000 width=97)
170 -> Seq Scan on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
174 postgres*# <span class="strong">NoMergeJoin(b a)</span>
176 postgres-# EXPLAIN SELECT *
177 postgres-# FROM pgbench_branches b
178 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid;
180 ---------------------------------------------------------------------------------
181 <span class="strong">Nested Loop</span> (cost=0.00..3891.01 rows=100000 width=197)
182 Join Filter: (b.bid = a.bid)
183 -> Seq Scan on pgbench_branches b (cost=0.00..1.01 rows=1 width=100)
184 -> Seq Scan on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
189 <p>テーブルの結合に対して、どんな順番で結合するか指定できるヒントのグループのことです。
190 結合の順番を指定したい場合は、結合順序のヒント(Leading)と、2つ以上のオブジェクトの名前を結合したい順番で指定してください。</p>
191 <p>以下に示した具体例について説明します。</br>
192 この例では、bテーブルとaテーブルを結合させた後、この結合テーブルとtテーブルを結合させるヒントを用いたため、実行計画作成時にヒントで指定したテーブル順でテーブル結合を選択しています。</p>
194 postgres*# <span class="strong">Leading(b a t)</span>
196 postgres-# EXPLAIN SELECT *
197 postgres-# FROM pgbench_branches b
198 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid
199 postgres-# JOIN pgbench_tellers t ON b.bid = t.bid;
201 --------------------------------------------------------------------------------------------------------------
202 Hash Join (cost=1.23..15399.49 rows=1000000 width=297)
203 <span class="strong">Hash Cond: (b.bid = t.bid)</span>
204 -> Nested Loop (cost=0.00..3898.27 rows=100000 width=197)
205 <span class="strong">Join Filter: (b.bid = a.bid)</span>
206 -> Index Scan using pgbench_branches_pkey on pgbench_branches b (cost=0.00..8.27 rows=1 width=100)
207 -> Seq Scan on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
208 -> Hash (cost=1.10..1.10 rows=10 width=100)
209 -> Seq Scan on pgbench_tellers t (cost=0.00..1.10 rows=10 width=100)
214 <p>1クエリ限りでGUCパラメータを設定できるヒントのグループのことです。
215 1クエリ限りでGUCパラメータを設定したい場合は、GUCパラメータを設定するためのヒント(Set)と、設定したいGUCパラメータとそのパラメータの値を指定してください。ただし、指定する値に小文字とアンダースコア(_)以外の文字(大文字、数字、空白スペースなど)を含む場合はダブルクォート(")で囲んでください。</p>
216 <p>以下に示した具体例について説明します。</br>
217 1つ目のSQL文は、GUCパラメータのenable_hashjoinとenable_nestloopをoffに設定するヒントを用いたため、実行計画作成時に各テーブル間の結合でMerge Joinを選択しています。</br>
218 2つ目のSQL文は、GUCパラメータのjoin_collapse_limitを1に設定するヒントを用いたため、実行計画作成時にFROM句で指定したテーブル順でテーブル結合を選択しています。</p>
220 postgres*# Set(enable_hashjoin off)
221 postgres*# Set(enable_nestloop off)
223 postgres-# EXPLAIN SELECT *
224 postgres-# FROM pgbench_branches b
225 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid
226 postgres-# JOIN pgbench_tellers t ON b.bid = t.bid;
228 ---------------------------------------------------------------------------------------------
229 <span class="strong">Merge Join</span> (cost=21888.11..37138.29 rows=1000000 width=297)
230 Merge Cond: (b.bid = a.bid)
231 -> <span class="strong">Merge Join</span> (cost=2.29..2.44 rows=10 width=200)
232 Merge Cond: (b.bid = t.bid)
233 -> Sort (cost=1.02..1.02 rows=1 width=100)
235 -> Seq Scan on pgbench_branches b (cost=0.00..1.01 rows=1 width=100)
236 -> Sort (cost=1.27..1.29 rows=10 width=100)
238 -> Seq Scan on pgbench_tellers t (cost=0.00..1.10 rows=10 width=100)
239 -> Materialize (cost=21885.82..22385.82 rows=100000 width=97)
240 -> Sort (cost=21885.82..22135.82 rows=100000 width=97)
242 -> Seq Scan on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
246 postgres*# Set(join_collapse_limit "1")
248 postgres-# EXPLAIN SELECT *
249 postgres-# FROM pgbench_branches b
250 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid
251 postgres-# JOIN pgbench_tellers t ON b.bid = t.bid;
253 --------------------------------------------------------------------------------------------------------------
254 Hash Join (cost=1.23..15399.49 rows=1000000 width=297)
255 Hash Cond: (b.bid = t.bid)
256 -> Nested Loop (cost=0.00..3898.27 rows=100000 width=197)
257 Join Filter: (b.bid = a.bid)
258 -> Index Scan using pgbench_branches_pkey on pgbench_branches b (cost=0.00..8.27 rows=1 width=100)
259 -> Seq Scan on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
260 -> Hash (cost=1.10..1.10 rows=10 width=100)
261 -> Seq Scan on pgbench_tellers t (cost=0.00..1.10 rows=10 width=100)
266 <h3 id="hint-GUC">pg_hint_planのGUCパラメータ</h3>
267 <p>pg_hint_planツールに関するGUCパラメータを以下に記述します。</p>
271 <tr><th>GUCパラメータ</th><th>説明</th><th>デフォルト値</th></tr>
274 <tr><td>pg_hint_plan.enable</td>
275 <td>on のとき、pg_hint_planの機能を有効にします。</td><td>on</td></tr>
276 <tr><td>pg_hint_plan.debug_print</td>
277 <td>on のとき、プランナが実行計画を生成するときに用いたヒントを表示します。</td><td>off</td></tr>
278 <tr><td>pg_hint_plan.parse_message</td>
279 <td>指定したヒントに対して、どのメッセージ階層を表示するかを指定します。有効な値は、debug5、debug4、debug3、debug2、debug1、log、info、notice、warningまたはerrorです。</td><td>info</td></tr>
283 <h2 id="restrictions">使用上の注意と制約</h2>
284 <p>pg_hint_planを使用する際には、以下の注意と制約があります。</p>
287 <dd>クエリの前に複数のブロックコメントを記述する場合は、最初のブロックコメントにのみヒントを記述してください。二番目以降のブロックコメントは、ヒントと見なされず無視されます。以下の例では、HashJoin(a b)とSeqScan(a)がヒントと見なされ、IndexScan(a)とMergeJoin(a b)は無視されています。</p>
290 postgres*# <span class="strong">HashJoin(a b)</span>
291 postgres*# <span class="strong">SeqScan(a)</span>
293 postgres-# /* IndexScan(a) */
294 postgres-# EXPLAIN SELECT /* MergeJoin(a b) */ *
295 postgres-# FROM pgbench_branches b
296 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid
297 postgres-# ORDER BY a.aid;
299 ---------------------------------------------------------------------------------------
300 Sort (cost=31465.84..31715.84 rows=100000 width=197)
302 -> <span class="strong">Hash Join</span> (cost=1.02..4016.02 rows=100000 width=197)
303 Hash Cond: (a.bid = b.bid)
304 -> <span class="strong">Seq Scan on pgbench_accounts a</span> (cost=0.00..2640.00 rows=100000 width=97)
305 -> Hash (cost=1.01..1.01 rows=1 width=100)
306 -> Seq Scan on pgbench_branches b (cost=0.00..1.01 rows=1 width=100)
311 <dt>オブジェクト名の指定方法</dt>
312 <dd><p>ヒント対象のオブジェクト名に小文字とアンダースコア(_)以外の文字(大文字、数字、空白スペースなど)を含む場合は、ダブルクォート(")で囲んでください。</p><p>また、クエリ中に同一名称のテーブルが複数回出現する場合(スキーマ違いや同一テーブルの複数回使用など)は、テーブルに別名をつけてそれぞれのテーブルを区別してください。以下の例の1つ目のSQL文では、MergeJoin(t1 t1)をヒントに指定したとき、ヒント対象のオブジェクトが特定できずにエラーになっています。2つ目のSQL文では、各テーブルにptやstという別名をつけているため、実行計画作成時にヒントで指定した通りにMerge Joinを選択しています。
315 postgres=# /* <span class="strong">MergeJoin(t1 t1)</span>*/
316 postgres-# EXPLAIN SELECT * FROM s1.t1
317 postgres-# JOIN public.t1 ON (s1.t1.id=public.t1.id);
318 INFO: hint syntax error at or near "t1 t1)"
319 <span class="strong">DETAIL: relation name "t1" is ambiguous</span>
320 INFO: hint syntax error at or near "t1 t1)"
321 <span class="strong">DETAIL: relation name "t1" is ambiguous</span>
323 --------------------------------------------------------------------
324 Hash Join (cost=270.00..323.05 rows=1230 width=44)
325 Hash Cond: (s1.t1.id = public.t1.id)
326 -> Seq Scan on t1 (cost=0.00..22.30 rows=1230 width=36)
327 -> Hash (cost=145.00..145.00 rows=10000 width=8)
328 -> Seq Scan on t1 (cost=0.00..145.00 rows=10000 width=8)
331 postgres=# /* <span class="strong">MergeJoin(pt st)</span> */
332 postgres-# EXPLAIN SELECT * FROM s1.t1 st
333 postgres-# JOIN public.t1 pt ON (st.id=pt.id);
335 ----------------------------------------------------------------------------------
336 <span class="strong">Merge Join</span> (cost=0.00..421.33 rows=1230 width=44)
337 Merge Cond: (st.id = pt.id)
338 -> Index Scan using t1_id_idx on t1 st (cost=0.00..62.70 rows=1230 width=36)
339 -> Index Scan using t1_pkey on t1 pt (cost=0.00..318.25 rows=10000 width=8)(4 rows)
345 <dd>pg_hint_planでは、ヒントの記述に誤りがあった場合は、誤った記述に関する情報を出力しますがエラー終了しません。誤った記述より前のヒントのみ有効となり、誤った記述以降のヒントを無視してクエリを実行します。</dd>
346 <dt>指定するヒントの種類の重複</dt>
347 <dd>同じオブジェクトに対して同じグループのヒントを重複して指定した場合は、最後に指定したヒントを使用します。</dd>
349 <dd>ビューを複数用いるときに、各ビュー内のテーブルの別名が重複した場合は、ヒントの対象を区別できません。区別する場合は、各ビュー内のテーブルの別名を重複させないでください。</dd>
352 <h2 id="known-issues">既知の問題</h2>
353 <p>pg_hint_planに関する既知の問題について説明します。</p>
355 <dt>副問い合わせを含むSELECT文</dt>
356 <dd id="view_limit">pg_hint_planの使用中に副問い合わせを含むSELECT文を実行すると、サーバ側で異常終了する場合があります。よって、pg_hint_planを試用しているときは、副問い合わせを含むSELECT文を実行しないでください。</dd>
359 <h2 id="seealso">関連項目</h2>
360 <h3 id="postgresql_document">PostgreSQLドキュメント</h3>
361 <a href="http://www.postgresql.org/docs/9.1/static/sql-explain.html">EXPLAIN</a>
364 <div class="navigation">
365 <a href="pg_hint_plan-ja.html">pg_hint_plan</a>
368 <p class="footer">Copyright (c) 2012, NIPPON TELEGRAPH AND TELEPHONE CORPORATION</p>
371 <script type="text/javascript">
372 var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
373 document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
374 </script><script src="pg_statsinfo-ja_files/ga.js" type="text/javascript"></script>
375 <script type="text/javascript">
377 var pageTracker = _gat._getTracker("UA-10244036-6");
378 pageTracker._trackPageview();