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-object">対象オブジェクトの指定方法</a></li>
35 <li><a href="#hint-type">ヒントのグループ</a></li>
36 <li><a href="#hint-GUC">pg_hint_planのGUCパラメータ</a></li>
39 <li><a href="#restrictions">使用上の注意と制約</a></li>
40 <li><a href="#known-issues">既知の問題</a></li>
41 <li><a href="#seealso">関連項目</a></li>
44 <h2 id="name">pg_hint_planとは?</h2>
45 <p>pg_hint_planは、元のSQL文を変えずに実行計画を制御するためのツールです。</p>
47 <h2 id="description">機能概要</h2>
48 <p>pg_hint_planは、SQL文の前にヒントを記述したブロックコメントを加えることで、ヒントに従って実行計画を制御することができます。</p>
50 <h2 id="install">インストール</h2>
51 <p>pg_hint_planのインストール方法について説明します。</p>
53 <h3 id="requirement">動作環境</h3>
57 <dd>バージョン 9.2devel 4月2日版</dd>
58 <dt>動作検証済みOS</dt><dd>RHEL 6.1</dd>
61 <h3 id="build">ビルド</h3>
62 <p>pg_hint_planをソースコードからビルドする場合、pg_hint_planのソースを展開したディレクトリでmake → make installの順に実行してください。なお、pg_hint_planのビルドにはpgxsを使用するので、RPM版のPostgreSQLを使用している環境では、postgresql-devel パッケージが必要です。</p>
65 $ tar xzvf pg_hint_plan-0.1.0.tar.gz
66 $ cd pg_hint_plan-0.1.0
71 <h2 id="uninstall">アンインストール</h2>
72 <p>pg_hint_planをアンインストールするには、pg_hint_planのソースを展開したディレクトリでmake uninstallを実行してください。</p>
73 <p>以下にアンインストールの例を示します。</p>
75 $ cd pg_hint_plan-0.1.0
79 <h2 id="usage">使い方</h2>
80 <p>pg_hint_planのヒントの使い方について説明します。</p>
82 <h3 id="hint-load">pg_hint_planのロード</h3>
83 <p>pg_hint_planを使うためには、pg_hint_planの共有ライブラリをロードしてください。</p>
86 postgres=# LOAD 'pg_hint_plan';
90 <h3 id="hint-rule">ヒントの記述方法</h3>
91 <p>ヒントはクエリの前にブロックコメントで記述してください。
92 クエリの前に複数のブロックコメントを記述する場合は、先頭のブロックコメントにのみヒントを記述してください。先頭以外のブロックコメントは、ヒントと見なされず無視されます。
93 また、複数のヒントを記述する場合は、スペース、タブまたは改行のいずれかで区切ってください。</p>
94 <p>以下に示した具体例について説明します。この例では、HashJoin(a b)とSeqScan(a)がヒントと見なされ、IndexScan(a)とMergeJoin(a b)は無視されています。</p>
97 postgres*# <strong>HashJoin(a b)</strong>
98 postgres*# <strong>SeqScan(a)</strong>
100 postgres-# /* IndexScan(a) */
101 postgres-# EXPLAIN SELECT /* MergeJoin(a b) */ *
102 postgres-# FROM pgbench_branches b
103 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid
104 postgres-# ORDER BY a.aid;
106 ---------------------------------------------------------------------------------------
107 Sort (cost=31465.84..31715.84 rows=100000 width=197)
109 -> <strong>Hash Join</strong> (cost=1.02..4016.02 rows=100000 width=197)
110 Hash Cond: (a.bid = b.bid)
111 -> <strong>Seq Scan on pgbench_accounts a</strong> (cost=0.00..2640.00 rows=100000 width=97)
112 -> Hash (cost=1.01..1.01 rows=1 width=100)
113 -> Seq Scan on pgbench_branches b (cost=0.00..1.01 rows=1 width=100)
117 <h3 id="hint-object">対象オブジェクトの指定方法</h3>
118 <p>ヒントの対象となるオブジェクトは、テーブルとビューとインデックスの3種類です。3種類のどの場合でもスキーマ修飾できません。また、どの場合でもオブジェクト名に小文字とアンダースコア(_)以外の文字(大文字、数字、空白スペースなど)を含む場合は、ダブルクォート(")で囲んでください。</br>
119 テーブルを対象にする場合は、テーブル名または別名(エイリアス)で指定してください。
120 ただし、スキーマが異なる同じ名前のテーブルを1クエリ中に用いる場合は、別名で指定してください。個々のテーブルを指定できるようにするためです。</p>
122 <p>以下に示した具体例について説明します。</br>
123 1つ目のSQL文では、MergeJoin(t1 t1)をヒントに指定したとき、ヒント対象のオブジェクト指定に失敗しています。これは、t1というテーブル名が2つ存在するために、テーブルを区別できなかったことが原因です。</br>
124 2つ目のSQL文では、各テーブルにptやstという別名をつけているため、実行計画作成時にヒントで指定した通りにMerge Joinを選択しています。
127 postgres=# /* <strong>MergeJoin(t1 t1)</strong>*/
128 postgres-# EXPLAIN SELECT * FROM s1.t1
129 postgres-# JOIN public.t1 ON (s1.t1.id=public.t1.id);
130 INFO: hint syntax error at or near "t1 t1)"
131 <strong>DETAIL: relation name "t1" is ambiguous</strong>
132 INFO: hint syntax error at or near "t1 t1)"
133 <strong>DETAIL: relation name "t1" is ambiguous</strong>
135 --------------------------------------------------------------------
136 Hash Join (cost=270.00..323.05 rows=1230 width=44)
137 Hash Cond: (s1.t1.id = public.t1.id)
138 -> Seq Scan on t1 (cost=0.00..22.30 rows=1230 width=36)
139 -> Hash (cost=145.00..145.00 rows=10000 width=8)
140 -> Seq Scan on t1 (cost=0.00..145.00 rows=10000 width=8)
143 postgres=# /* <strong>MergeJoin(pt st)</strong> */
144 postgres-# EXPLAIN SELECT * FROM s1.t1 st
145 postgres-# JOIN public.t1 pt ON (st.id=pt.id);
147 ----------------------------------------------------------------------------------
148 <strong>Merge Join</strong> (cost=0.00..421.33 rows=1230 width=44)
149 Merge Cond: (st.id = pt.id)
150 -> Index Scan using t1_id_idx on t1 st (cost=0.00..62.70 rows=1230 width=36)
151 -> Index Scan using t1_pkey on t1 pt (cost=0.00..318.25 rows=10000 width=8)(4 rows)
154 <p>ビューを対象とする場合は、テーブルを対象とする場合に加えて制限事項が存在します。<a href="#view_limit">ビューに対する制限</a>を参照してください</p>
155 <p>インデックスを対象にする場合は、インデックス名で指定してください。なお、インデックス名のみを対象とするヒントはありません。</p>
156 <p>以下に示した具体例について説明します。</br>この例では、IndexScanヒントに対してt1テーブルの他にt1_valインデックスを指定したため、実行計画作成時にt1_valインデックスを用いたIndex Scanを選択しています。</p>
158 postgres=# /* <strong>IndexScan</strong>(t1 <strong>t1_val</strong>) */
159 postgres-# EXPLAIN SELECT * FROM t1
160 postgres-# WHERE id < 5
161 postgres-# AND val < 3;
163 -------------------------------------------------------------------
164 <strong>Index Scan</strong> using <strong>t1_val</strong> on t1 (cost=0.00..190.19 rows=1 width=8)
165 Index Cond: (val < 3)
172 <h3 id="hint-type">ヒントのグループ</h3>
173 <p>pg_hint_planで使えるヒントのグループは、スキャン方式と結合方式、結合順序、GUCパラメータの4通りに分けられます。同じグループのヒントを同じオブジェクトに対して指定した場合は、最後に指定したヒントが適用されます。各グループの具体的なヒントは、<a href="hint_list-ja.html">ヒント一覧</a>を参照してください。</p>
176 <p>テーブルに対して、どんなスキャンを選択するか指定できるヒントのグループのことです。
177 特定のテーブルに対するスキャン方式を選択したい場合は、そのスキャン方式のヒントと、対象となるオブジェクトの名前を指定してください。
178 特定のテーブルに対するスキャン方式を選択してほしくない場合は、そのスキャン方式のヒントの先頭に No を記述した上で、対象となるオブジェクトの名前を指定してください。</p>
179 <p>以下に示した具体例について説明します。</br>
180 1つ目のSQL文では、aテーブルにIndex Scanを選択させるヒントを用いたため、実行計画作成時にaテーブルに対してIndex Scanを選択しています。</br>
181 2つ目のSQL文では、aテーブルにIndex Scan以外を選択させるヒントを用いたため、実行計画作成時にaテーブルに対してIndex Scan以外のスキャン方式であるSeq Scanを選択しています。</p>
182 <pre>postgres=# /* <strong>IndexScan(a)</strong> */
183 postgres-# EXPLAIN SELECT *
184 postgres-# FROM pgbench_accounts a
185 postgres-# ORDER BY aid;
187 ---------------------------------------------------------------------------------------------------------
188 <strong>Index Scan</strong> using pgbench_accounts_pkey on pgbench_accounts a (cost=0.00..4247.26 rows=100000 width=97)
191 postgres=# /* <strong>NoIndexScan(a)</strong> */
192 postgres-# EXPLAIN SELECT *
193 postgres-# FROM pgbench_accounts a
194 postgres-# ORDER BY aid;
196 ---------------------------------------------------------------------------------
197 Sort (cost=21885.82..22135.82 rows=100000 width=97)
199 -> <strong>Seq Scan</strong> on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
205 <p>テーブルの結合に対して、どんな結合を選択するか指定できるヒントのグループのことです。
206 特定の結合方式を選択したい場合は、その結合方式のヒントと、対象となる2つ以上のオブジェクトの名前を指定してください。
207 特定の結合方式を選択してほしくない場合は、その結合方式のヒントの先頭に No を記述した上で、対象となるオブジェクトの名前を指定してください。</p>
208 <p>以下に示した具体例について説明します。</br>
209 1つ目のSQL文では、aテーブルとbテーブルの結合にMerge Joinを選択させるヒントを用いたため、実行計画作成時にMerge Joinを選択しています。</br>
210 2つ目のSQL文では、aテーブルとbテーブルの結合にMerge Join以外を選択させるヒントを用いたため、実行計画作成時にMerge Join以外の結合方式であるNested Loopを選択しています。</p>
213 postgres*# <strong>MergeJoin(b a)</strong>
215 postgres-# EXPLAIN SELECT *
216 postgres-# FROM pgbench_branches b
217 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid;
219 ---------------------------------------------------------------------------------------------
220 <strong>Merge Join</strong> (cost=21886.84..23636.85 rows=100000 width=197)
221 Merge Cond: (b.bid = a.bid)
222 -> Sort (cost=1.02..1.02 rows=1 width=100)
224 -> Seq Scan on pgbench_branches b (cost=0.00..1.01 rows=1 width=100)
225 -> Materialize (cost=21885.82..22385.82 rows=100000 width=97)
226 -> Sort (cost=21885.82..22135.82 rows=100000 width=97)
228 -> Seq Scan on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
232 postgres*# <strong>NoMergeJoin(b a)</strong>
234 postgres-# EXPLAIN SELECT *
235 postgres-# FROM pgbench_branches b
236 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid;
238 ---------------------------------------------------------------------------------
239 <strong>Nested Loop</strong> (cost=0.00..3891.01 rows=100000 width=197)
240 Join Filter: (b.bid = a.bid)
241 -> Seq Scan on pgbench_branches b (cost=0.00..1.01 rows=1 width=100)
242 -> Seq Scan on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
247 <p>テーブルの結合に対して、どんな順番で結合するか指定できるヒントのグループのことです。
248 結合の順番を指定したい場合は、結合順序のヒント(Leading)と、2つ以上のオブジェクトの名前を結合したい順番で指定してください。</p>
249 <p>以下に示した具体例について説明します。</br>
250 この例では、bテーブルとaテーブルを結合させた後、この結合テーブルとtテーブルを結合させるヒントを用いたため、実行計画作成時にヒントで指定したテーブル順でテーブル結合を選択しています。</p>
252 postgres*# <strong>Leading(b a t)</strong>
254 postgres-# EXPLAIN SELECT *
255 postgres-# FROM pgbench_branches b
256 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid
257 postgres-# JOIN pgbench_tellers t ON b.bid = t.bid;
259 --------------------------------------------------------------------------------------------------------------
260 Hash Join (cost=1.23..15399.49 rows=1000000 width=297)
261 <strong>Hash Cond: (b.bid = t.bid)</strong>
262 -> Nested Loop (cost=0.00..3898.27 rows=100000 width=197)
263 <strong>Join Filter: (b.bid = a.bid)</strong>
264 -> Index Scan using pgbench_branches_pkey on pgbench_branches b (cost=0.00..8.27 rows=1 width=100)
265 -> Seq Scan on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
266 -> Hash (cost=1.10..1.10 rows=10 width=100)
267 -> Seq Scan on pgbench_tellers t (cost=0.00..1.10 rows=10 width=100)
272 <p>1クエリ限りでGUCパラメータを設定できるヒントのグループのことです。
273 1クエリ限りでGUCパラメータを設定したい場合は、GUCパラメータを設定するためのヒント(Set)と、設定したいGUCパラメータとそのパラメータの値を指定してください。ただし、指定する値に小文字とアンダースコア(_)以外の文字(大文字、数字、空白スペースなど)を含む場合はダブルクォート(")で囲んでください。</p>
274 <p>以下に示した具体例について説明します。</br>
275 1つ目のSQL文は、GUCパラメータのenable_hashjoinとenable_nestloopをoffに設定するヒントを用いたため、実行計画作成時に各テーブル間の結合でMerge Joinを選択しています。</br>
276 2つ目のSQL文は、GUCパラメータのjoin_collapse_limitを1に設定するヒントを用いたため、実行計画作成時にFROM句で指定したテーブル順でテーブル結合を選択しています。</p>
278 postgres*# Set(enable_hashjoin off)
279 postgres*# Set(enable_nestloop off)
281 postgres-# EXPLAIN SELECT *
282 postgres-# FROM pgbench_branches b
283 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid
284 postgres-# JOIN pgbench_tellers t ON b.bid = t.bid;
286 ---------------------------------------------------------------------------------------------
287 <strong>Merge Join</strong> (cost=21888.11..37138.29 rows=1000000 width=297)
288 Merge Cond: (b.bid = a.bid)
289 -> <strong>Merge Join</strong> (cost=2.29..2.44 rows=10 width=200)
290 Merge Cond: (b.bid = t.bid)
291 -> Sort (cost=1.02..1.02 rows=1 width=100)
293 -> Seq Scan on pgbench_branches b (cost=0.00..1.01 rows=1 width=100)
294 -> Sort (cost=1.27..1.29 rows=10 width=100)
296 -> Seq Scan on pgbench_tellers t (cost=0.00..1.10 rows=10 width=100)
297 -> Materialize (cost=21885.82..22385.82 rows=100000 width=97)
298 -> Sort (cost=21885.82..22135.82 rows=100000 width=97)
300 -> Seq Scan on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
304 postgres*# Set(join_collapse_limit "1")
306 postgres-# EXPLAIN SELECT *
307 postgres-# FROM pgbench_branches b
308 postgres-# JOIN pgbench_accounts a ON b.bid = a.bid
309 postgres-# JOIN pgbench_tellers t ON b.bid = t.bid;
311 --------------------------------------------------------------------------------------------------------------
312 Hash Join (cost=1.23..15399.49 rows=1000000 width=297)
313 Hash Cond: (b.bid = t.bid)
314 -> Nested Loop (cost=0.00..3898.27 rows=100000 width=197)
315 Join Filter: (b.bid = a.bid)
316 -> Index Scan using pgbench_branches_pkey on pgbench_branches b (cost=0.00..8.27 rows=1 width=100)
317 -> Seq Scan on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
318 -> Hash (cost=1.10..1.10 rows=10 width=100)
319 -> Seq Scan on pgbench_tellers t (cost=0.00..1.10 rows=10 width=100)
324 <h3 id="hint-GUC">pg_hint_planのGUCパラメータ</h3>
325 <p>pg_hint_planツールに関するGUCパラメータを以下に記述します。</p>
329 <tr><th>GUCパラメータ</th><th>説明</th><th>デフォルト値</th></tr>
332 <tr><td>pg_hint_plan.enable</td>
333 <td>on のとき、pg_hint_planの機能を有効にします。</td><td>on</td></tr>
334 <tr><td>pg_hint_plan.debug_print</td>
335 <td>on のとき、プランナが実行計画を生成するときに用いたヒントを表示します。</td><td>off</td></tr>
336 <tr><td>pg_hint_plan.parse_message</td>
337 <td>指定したヒントに対して、どのメッセージ階層を表示するかを指定します。有効な値は、debug5、debug4、debug3、debug2、debug1、log、info、notice、warningまたはerrorです。</td><td>info</td></tr>
341 <h2 id="restrictions">使用上の注意と制約</h2>
342 <p>pg_hint_planを使用する際には、以下の注意と制約があります。</p>
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();