<p>ヒント用コメントと通常のコメントを区別するために、ヒント用のブロックコメントは「<span class="bold">/*+</span>」で始めます。ヒントの対象は、カッコ内にオブジェクト名または別名で指定します。オブジェクト名は、スペース、タブ、または改行のいずれかで区切って指定します。</p>
<p>以下の例では、HashJoinとSeqScanヒント句により、pgbench_accountsテーブルに対するSeq Scanの結果をHash Joinする実行計画が選択されています。なおかつ、Setヒント句によりこのクエリの実行計画を作成する間だけrandom_page_costが2.0に変更されています。</p>
<pre>
-<b>postgres=#</b> EXPLAIN (VERBOSE, COSTS)
-<b>postgres-# /*+</b>
-<b>postgres*# SeqScan(a)</b>
-<b>postgres*# HashJoin(a b)</b>
-<b>postgres*# Set(random_page_cost 2.0)</b>
-<b>postgres*# */</b>
-<b>postgres-#</b> SELECT *
-<b>postgres-#</b> FROM pgbench_accounts a
-<b>postgres-#</b> JOIN pgbench_branches b
-<b>postgres-#</b> ON a.bid = b.bid
-<b>postgres-#</b> ORDER BY a.aid
-<b>postgres-#</b> LIMIT 10;
+<span class="strong">postgres=#</span> EXPLAIN (VERBOSE, COSTS)
+<span class="strong">postgres-# /*+</span>
+<span class="strong">postgres*# SeqScan(a)</span>
+<span class="strong">postgres*# HashJoin(a b)</span>
+<span class="strong">postgres*# Set(random_page_cost 2.0)</span>
+<span class="strong">postgres*# */</span>
+<span class="strong">postgres-#</span> SELECT *
+<span class="strong">postgres-#</span> FROM pgbench_accounts a
+<span class="strong">postgres-#</span> JOIN pgbench_branches b
+<span class="strong">postgres-#</span> ON a.bid = b.bid
+<span class="strong">postgres-#</span> ORDER BY a.aid
+<span class="strong">postgres-#</span> LIMIT 10;
QUERY PLAN
----------------------------------------------------------------------------------------------------
Limit (cost=6176.99..6177.01 rows=10 width=461)
<p>以下の例では、ヒントの登録、ヒント登録情報の変更、ヒントの解除の順に、クエリの実行結果を示しています。
</p>
<pre>
-<b>postgres=#</b> INSERT INTO hint_plan.hints(norm_query_string, application_name, hints)
-<b>postgres-#</b> VALUES (
-<b>postgres(#</b> 'EXPLAIN (COSTS false) SELECT * FROM t1 WHERE t1.id = ?;',
-<b>postgres(#</b> '',
-<b>postgres(#</b> 'SeqScan(t1)'
-<b>postgres(#</b> );
+<span class="strong">postgres=#</span> INSERT INTO hint_plan.hints(norm_query_string, application_name, hints)
+<span class="strong">postgres-#</span> VALUES (
+<span class="strong">postgres(#</span> 'EXPLAIN (COSTS false) SELECT * FROM t1 WHERE t1.id = ?;',
+<span class="strong">postgres(#</span> '',
+<span class="strong">postgres(#</span> 'SeqScan(t1)'
+<span class="strong">postgres(#</span> );
INSERT 0 1
-<b>postgres=#</b> UPDATE hint_plan.hints
-<b>postgres-#</b> SET hints = 'IndexScan(t1)'
-<b>postgres-#</b> WHERE id = 1;
+<span class="strong">postgres=#</span> UPDATE hint_plan.hints
+<span class="strong">postgres-#</span> SET hints = 'IndexScan(t1)'
+<span class="strong">postgres-#</span> WHERE id = 1;
UPDATE 1
-<b>postgres=#</b> DELETE FROM hint_plan.hints
-<b>postgres-#</b> WHERE id = 1;
+<span class="strong">postgres=#</span> DELETE FROM hint_plan.hints
+<span class="strong">postgres-#</span> WHERE id = 1;
DELETE 1
-<b>postgres=#</b>
+<span class="strong">postgres=#</span>
</pre>
<p>なお、ヒントの登録や変更や解除はスーパーユーザでのみ可能です。一般ユーザでヒントの登録や変更や解除を実施したい場合は、スーパーユーザから一般ユーザにhint_plan.hintsテーブルの各権限を付与してください。</p>
<p>以下の例では、hint_plan.hintsテーブルに対してINSERT権限を持たない一般ユーザがヒントの登録を実施しようとしたときの結果を示しています。</p>
<pre>
-<b>postgres=></b> INSERT INTO hint_plan.hints(norm_query_string, application_name, hints)
-<b>postgres-></b> VALUES (
-<b>postgres(></b> 'EXPLAIN (COSTS false) SELECT * FROM t1 WHERE t1.id = ?;',
-<b>postgres(></b> '',
-<b>postgres(></b> 'SeqScan(t1)'
-<b>postgres(></b> );
+<span class="strong">postgres=></span> INSERT INTO hint_plan.hints(norm_query_string, application_name, hints)
+<span class="strong">postgres-></span> VALUES (
+<span class="strong">postgres(></span> 'EXPLAIN (COSTS false) SELECT * FROM t1 WHERE t1.id = ?;',
+<span class="strong">postgres(></span> '',
+<span class="strong">postgres(></span> 'SeqScan(t1)'
+<span class="strong">postgres(></span> );
ERROR: permission denied for relation hints
-<b>postgres=></b>
+<span class="strong">postgres=></span>
</pre>
<p>以下の例では、テーブルに登録した「コメントでの指定」の例と同じヒントと、登録したクエリの実行結果を示しています。</p>
<pre>
-<b>postgres=#</b> SELECT * FROM hint_plan.hints;
+<span class="strong">postgres=#</span> SELECT * FROM hint_plan.hints;
id | norm_query_string | application_name | hints
----+----------------------------+------------------+--------------------------------------------------
1 | EXPLAIN (VERBOSE, COSTS) +| psql | SeqScan(a)HashJoin(a b)Set(random_page_cost 2.0)
| | |
...
-<b>postgres=#</b> SET pg_hint_plan.enable_hint_table TO on;
-<b>postgres=#</b> EXPLAIN (VERBOSE, COSTS)
-<b>postgres-#</b> SELECT *
-<b>postgres-#</b> FROM pgbench_accounts a
-<b>postgres-#</b> JOIN pgbench_branches b
-<b>postgres-#</b> ON a.bid = b.bid
-<b>postgres-#</b> ORDER BY a.aid
-<b>postgres-#</b> LIMIT 10;
+<span class="strong">postgres=#</span> SET pg_hint_plan.enable_hint_table TO on;
+<span class="strong">postgres=#</span> EXPLAIN (VERBOSE, COSTS)
+<span class="strong">postgres-#</span> SELECT *
+<span class="strong">postgres-#</span> FROM pgbench_accounts a
+<span class="strong">postgres-#</span> JOIN pgbench_branches b
+<span class="strong">postgres-#</span> ON a.bid = b.bid
+<span class="strong">postgres-#</span> ORDER BY a.aid
+<span class="strong">postgres-#</span> LIMIT 10;
QUERY PLAN
----------------------------------------------------------------------------------------------------
Limit (cost=6176.99..6177.01 rows=10 width=461)
-> Sort (cost=6176.99..6426.99 rows=100000 width=461)
Output: a.aid, a.bid, a.abalance, a.filler, b.bid, b.bbalance, b.filler, a.aid
Sort Key: a.aid
- -> <b><u>Hash Join</u></b> (cost=1.02..4016.02 rows=100000 width=461)
+ -> <span class="strong">Hash Join</span> (cost=1.02..4016.02 rows=100000 width=461)
Output: a.aid, a.bid, a.abalance, a.filler, b.bid, b.bbalance, b.filler, a.aid
Hash Cond: (a.bid = b.bid)
- -> <b><u>Seq Scan on public.pgbench_accounts a</u></b> (cost=0.00..2640.00 rows=100000 width=97)
+ -> <span class="strong">Seq Scan on public.pgbench_accounts a</span> (cost=0.00..2640.00 rows=100000 width=97)
Output: a.aid, a.bid, a.abalance, a.filler
-> Hash (cost=1.01..1.01 rows=1 width=364)
Output: b.bid, b.bbalance, b.filler
<p>結合対象のテーブルが3つ以上ある場合、結合方式のヒント句を指定したとしてもコスト見積もりによっては対象のテーブルが直接結合されないことがあります。対象のテーブルが直接結合されない場合は、結合順序のヒント句を併せて指定します。</p>
<p>以下の例では、table1とtable2を直接結合する場合はNested Loopを、table1とtable2とtable3を結合する場合はMerge Joinを指定しています。また、コスト見積もりによってはtable1とtable2が直接結合されない場合を避けるため、table1とtable2を結合してからtable3を結合するようにLeadingヒント句を併用しています。</p>
<pre>
-<b>postgres=# /*+</b>
-<b>postgres*# NestLoop(t1 t2)</b>
-<b>postgres*# MergeJoin(t1 t2 t3)</b>
-<b>postgres*# Leading(t1 t2 t3)</b>
-<b>postgres*# */</b>
-<b>postgres-#</b> SELECT * FROM table1 t1
-<b>postgres-#</b> JOIN table table2 t2 ON (t1.key = t2.key)
-<b>postgres-#</b> JOIN table table3 t3 ON (t2.key = t3.key);
+<span class="strong">postgres=# /*+</span>
+<span class="strong">postgres*# NestLoop(t1 t2)</span>
+<span class="strong">postgres*# MergeJoin(t1 t2 t3)</span>
+<span class="strong">postgres*# Leading(t1 t2 t3)</span>
+<span class="strong">postgres*# */</span>
+<span class="strong">postgres-#</span> SELECT * FROM table1 t1
+<span class="strong">postgres-#</span> JOIN table table2 t2 ON (t1.key = t2.key)
+<span class="strong">postgres-#</span> JOIN table table3 t3 ON (t2.key = t3.key);
...
</pre>
</div>
<h4>結合方向</h4>
<p>上記の結合順序の指定を行なった際にはプランナの都合により結合方向(外部表/内部表もしくは駆動表/被駆動表の別)が期待とは異なるものになる場合があります。このような状況に対して結合方向を固定したい場合はもうひとつの書式を使う必要があります。</p>
<pre>
-<b>postgres=# /*+ Leading((t1 (t2 t3))) */</b> SELECT...
+<span class="strong">postgres=# /*+ Leading((t1 (t2 t3))) */</span> SELECT...
</pre>
<p>この書式では2つの要素を丸括弧で囲ったものがネストする形になっており、一つの括弧内では1つ目の要素が外部/駆動表、2番めの要素が内部/被駆動表として結合されます。</p>
<h4>見積もり件数補正</h4>
<p>見積もり件数補正対象として指定できるオブジェクトは結合方式と同じです。補正できるのは結合結果の見積もり件数だけで、スキャンの見積もり件数を補正することはできません。</p>
<p>以下の例では、テーブルaとテーブルbの結合結果の件数を、ヒント句で指定した値に補正しています。</p>
<pre>
-<b>postgres=# /*+ Rows(a b #10) */</b>
-<b>postgres-#</b> EXPLAIN SELECT *
-<b>postgres-#</b> FROM pgbench_branches b
-<b>postgres-#</b> JOIN pgbench_accounts a ON b.bid = a.bid
-<b>postgres-#</b> WHERE aid < 20
-<b>postgres-#</b> ORDER BY a.aid;
+<span class="strong">postgres=# /*+ Rows(a b #10) */</span>
+<span class="strong">postgres-#</span> EXPLAIN SELECT *
+<span class="strong">postgres-#</span> FROM pgbench_branches b
+<span class="strong">postgres-#</span> JOIN pgbench_accounts a ON b.bid = a.bid
+<span class="strong">postgres-#</span> WHERE aid < 20
+<span class="strong">postgres-#</span> ORDER BY a.aid;
QUERY PLAN
--------------------------------------------------------------------------------------------------------
- Nested Loop (cost=0.29..9.92 rows=<b><u>10</u></b> width=461)
+ Nested Loop (cost=0.29..9.92 rows=<span class="strong">10</span> width=461)
Join Filter: (b.bid = a.bid)
-> Index Scan using pgbench_accounts_pkey on pgbench_accounts a (cost=0.29. .8.62 rows=19 width=97)
Index Cond: (aid < 20)
<p>3番目のパラメータは強制の程度を指定します。 "soft" は max_parallel_workers_per_gather のみを変更して適用はプランナに任せます。"hard" は他のプランナ変数も変更するなどしてワーカ数を強制します。</p>
<p>以下の例では、テーブル c1 とテーブル c2 の結合で各々異なるワーカ数を強制します。</p>
<pre>
-<b>postgres=#</b> explain <b>/*+ Parallel(c1 3 hard) Parallel(c2 5 hard) */</b>
+<span class="strong">postgres=#</span> explain <span class="strong">/*+ Parallel(c1 3 hard) Parallel(c2 5 hard) */</span>
select c2.a from c1 join c2 on (c1.a = c2.a);
QUERY PLAN
-------------------------------------------------------------------------------
Hash Join (cost=2.86..11406.38 rows=101 width=4)
Hash Cond: (c1.a = c2.a)
-> Gather (cost=0.00..7652.13 rows=1000101 width=4)
- <b><u>Workers Planned: 3</u></b>
- -> Parallel Seq Scan on <b><u>c1</u></b> (cost=0.00..7652.13 rows=322613 width=4)
+ <span class="strong">Workers Planned: 3</span>
+ -> Parallel Seq Scan on <span class="strong">c1</span> (cost=0.00..7652.13 rows=322613 width=4)
-> Hash (cost=1.59..1.59 rows=101 width=4)
-> Gather (cost=0.00..1.59 rows=101 width=4)
- <b><u>Workers Planned: 5</u></b>
- -> Parallel Seq Scan on <b><u>c2</u></b> (cost=0.00..1.59 rows=59 width=4)
+ <span class="strong">Workers Planned: 5</span>
+ -> Parallel Seq Scan on <span class="strong">c2</span> (cost=0.00..1.59 rows=59 width=4)
</pre>
<h4>GUCパラメータ</h4>
<h2 id="restrictions">ヒントの指定に関する詳細</h2>
<p>以下にいくつかのトピックに関してヒントの動作について説明します。</p>
<dl>
-<dt><h3>コメント指定でのヒント記述位置と文法</h3></dt>
+<dt>コメント指定でのヒント記述位置と文法</dt>
<dd>ヒントはクエリの先頭または途中に記述できます。ただし、ヒントをクエリの途中に記述する場合、ヒント用のブロックコメントより前に以下の文字<span class="strong">以外</span>が含まれると、「/*+」で始まるコメントでもヒントと見なされず無視されます。
<ul>
<li>空白文字(半角スペース、水平/垂直タブ、改行、フォームフィード、復帰)</li>
postgres=# </pre>
</dd>
-<dt><h3>PL/pgSQL中の個別のクエリに対するヒント</h3></dt>
+<dt>PL/pgSQL中の個別のクエリに対するヒント</dt>
<dd>ヒントは、PL/pgSQLブロック中の各クエリにも指定できます。ただし、以下のような制約があります。
<ul>
<li>指定したヒントが適用されるSQLは以下の通りです。他のSQLにヒントを指定しても適用されません。
postgres$# id integer;
postgres$# cnt integer;
postgres$# BEGIN
-postgres$# SELECT <b><u>/*+ NoIndexScan(a) */</u></b> aid
+postgres$# SELECT <span class="strong">/*+ NoIndexScan(a) */</span> aid
postgres$# INTO id FROM pgbench_accounts a WHERE aid = $1;
-postgres$# SELECT <b><u>/*+ SeqScan(a) */</u></b> count(*)
+postgres$# SELECT <span class="strong">/*+ SeqScan(a) */</span> count(*)
postgres$# INTO cnt FROM pgbench_accounts a;
postgres$# RETURN id + cnt;
postgres$# END;
postgres$# $$ LANGUAGE plpgsql;
</pre>
</dd>
-<dt><h3>ヒント句内のオブジェクト名の文字ケース</h3></dt>
+<dt>ヒント句内のオブジェクト名の文字ケース</dt>
<dd>PostgreSQL は引用符で囲われないオブジェクト名を文字ケースを無視して扱いますが、pg_hint_plan は指定されたオブジェクト名の文字ケースはそのまま PostgreSQL の内部表現と比較します。つまり、ヒント句で TBL と指定した場合、データベース上で "TBL" と定義したもののみと合致し, TBL, tbl, Tbl など引用符で囲われないオブジェクト名とは合致しません。</dd>
-<dt><h3>ヒント句内のオブジェクト名の引用符付け</h3></dt>
+<dt>ヒント句内のオブジェクト名の引用符付け</dt>
<dd>ヒントに記述するオブジェクト名や別名が括弧((、)のいずれか)、二重引用符(")、空白(スペース、タブ、改行のいずれか)を含む場合は、通常のSQL文で使う場合と同じように二重引用符(")で囲んでください。二重引用符を含むオブジェクト名は、全体を二重引用符で括ったうえで、内部に含む二重引用符を二重引用符でエスケープしてください(例: 「quoted"table"name」→「"quoted""table""name"」)。</dd>
-<dt><h3>同一名称テーブルの区別</h3></dt>
+<dt>同一名称テーブルの区別</dt>
<dd>スキーマ違いや同一テーブルの複数回使用などでクエリ中に同一名称のテーブルが複数回出現する場合は、テーブルに別名をつけてそれぞれのテーブルを区別してください。以下の例の1つ目のSQL文では、HashJoin(t1 t1)をヒントに指定したとき、ヒント句対象のオブジェクトが特定できずにエラーになっています。2つ目のSQL文では、各テーブルにptやstという別名をつけているため、実行計画作成時にヒントで指定した通りにHash Joinを選択しています。</p>
<pre>
postgres=# /*+ <span class="strong">HashJoin(t1 t1)</span>*/
</p>
</dd>
<dl>
-<dt><h3>ビューおよびルールの中でアクセスされているテーブル</h3></dt>
+<dt>ビューおよびルールの中でアクセスされているテーブル</dt>
<dd>ヒント句で指定した名称と一致すれば、ビュー定義や関数内クエリなどに出現するテーブルについても、ヒントを指定したクエリ内と同じようにヒント句が適用されます。このため、ヒント句の適用有無や適用するヒント句をそれぞれのテーブルで変えたい場合は、それぞれ異なる別名を指定してください。</br>
以下の例では、ビュー定義で使われている「t1」という別名をSeqScanヒント句で指定したことで、表スキャンとビュー経由のスキャンの両方でSeq Scanが選択されています。ビュー定義で使用されている「t1」とは別の別名を実表に指定することで、個別にスキャン方式を制御できます。
<pre>
Filter: (key = 1)
</pre>
</dd>
-<dt><h3>継承テーブル</h3></dt>
+<dt>継承テーブル</dt>
<dd>継承テーブルにスキャン方式のヒント句を指定する場合は、オブジェクト名として親テーブルの名称または別名を指定してください。全ての子テーブルに同じスキャン方式を選択します。子テーブルごとに別のスキャン方式を指定することはできません。</dd>
-<dt><h3>マルチステートメント</h3></dt>
+<dt>マルチステートメント</dt>
<dd>クエリをマルチステートメントで実行する場合は、ヒントの指定方法によって以下のように注意点が異なります。
<dl>
<dt>コメントでの指定</dt>
<dd>ヒントを指定したいクエリの定数部分を?に置き換えてから、全てのクエリを一つにまとめてヒント用テーブルに登録します。ただし、複数の動的クエリをマルチステートメントで実行する場合には対応していません。</dd>
</dl>
</dd>
-<dt><h3>FROM句にVALUES式を使っている問い合わせ</h3></dt>
+<dt>FROM句にVALUES式を使っている問い合わせ</dt>
<dd>FROM句にVALUES式を使っている場合は、ヒント句のオブジェクト名に「*VALUES*」を指定することでヒントを与えることができる場合があります。 ただし複数のVALUESを使っている場合は内部的には区別がつかないためヒントを与えることはできません。
<pre>
postgres=# /*+ <span class="strong">MergeJoin(a *VALUES*)</span> */
postgres-# ORDER BY a.aid;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------
- <b><u>Merge Join</u></b> (cost=0.04..4497.33 rows=2 width=105)
+ <span class="strong">Merge Join</span> (cost=0.04..4497.33 rows=2 width=105)
Merge Cond: (a.aid = "*VALUES*".column1)
-> Index Scan using pgbench_accounts_pkey on pgbench_accounts a (cost=0.00..4247.26 rows=100000 width=97)
-> Sort (cost=0.04..0.04 rows=2 width=8)
Sort Key: "*VALUES*".column1
- -> Values Scan on <b><u>"*VALUES*"</u></b> (cost=0.00..0.03 rows=2 width=8)
+ -> Values Scan on <span class="strong">"*VALUES*"</span> (cost=0.00..0.03 rows=2 width=8)
postgres=#
</pre>
</dd>
</dl>
-<dt><h3>副問い合わせ結果</h3></dt>
+<dt>副問い合わせ結果</dt>
<dd>以下のような形式の副問い合わせでは外側の文への併合が行われず「ANY_subquery」という名前の独立した副問合せとして残される場合があります。このような副問合せが一つしかない場合は ANY_subquery という名前でこの副問合せを特定することができます。
<ul>
-<li>IN (SELECT ... { <b>LIMIT | OFFSET 等</b>} ... )</li>
-<li>ANY (SELECT ... { <b>LIMIT | OFFSET 等</b>} ...)</li>
-<li>SOME (SELECT ... { <b>LIMIT | OFFSET 等</b>} ...)</li>
+<li>IN (SELECT ... { <span class="strong">LIMIT | OFFSET 等</span>} ... )</li>
+<li>ANY (SELECT ... { <span class="strong">LIMIT | OFFSET 等</span>} ...)</li>
+<li>SOME (SELECT ... { <span class="strong">LIMIT | OFFSET 等</span>} ...)</li>
</ul>
以下の例では、そのことを利用して Hash Joinを強制しています。
<pre>
postgres=#
</pre>
-<dt><h3>IndexOnlyScanヒント句</h3></dt>
-<dd>ヒント句の対象となるテーブルにIndex Only Scanが可能なインデックスとIndex Only Scanが不可能なインデックスが同時に存在する場合、Index Only Scanが可能なインデックスをテーブルに対してIndexOnlyScanヒント句を追加で指定しないとIndex Scanが選択されることがあります。</dd>
+<dt>IndexOnlyScanヒント句</dt>
+<dd>IndexOnlyScanヒントで指定されているインデックスで index only scan が実行できない場合は、index scan を他のインデックスで実行する可能性があります。</dd>
-<dt><h3>NoIndexScanヒントの挙動について</h3></dt>
+<dt>NoIndexScanヒントの挙動について</dt>
<dd>NoIndexScanヒント句を指定した場合は、Index ScanだけでなくIndex Only Scanも選択されません。</dd>
</dl>
-<dt><h3>UNION に対する並列実行ヒント</h3></dt>
+<dt>UNION に対する並列実行ヒント</dt>
<dd>UNIONは直下のサブクエリが全て並列実行可能な場合にだけ並列実行を行います。一方ですべてのサブクエリが並列実行可能な場合は、そのうちの一つで並列実行を強制するとコスト比較の結果UNION全体が並列実行されることになります。ただし並列実行ヒントによる並列実行の禁止を行った場合はそのスキャンは並列実行不可となります。
</dd>
</dl>
-<dt><h3>Set ヒントでの pg_hint_plan 自身の制御変数の設定</h3></dt>
+<dt>Set ヒントでの pg_hint_plan 自身の制御変数の設定</dt>
<dd>pg_hint_plan 自身の挙動を設定する変数を Set ヒントで変更した場合は期待通りに動作しない場合があります。</dd>
<ul>
<li>enable_hint, enable_hint_tables の設定ヒントはログ上は「使用済み」と出ますが、実際には無視されています。</li>
</dd>
<h2>ヒントのパースエラーについて</h2>
-<dt><h3>構文エラー</h3></dt>
+<dt>構文エラー</dt>
<dd>ヒント句の記述に構文上の誤りがあった場合、pg_hint_planは誤った記述より前のヒント句のみ有効とし、誤った記述以降のヒント句を無視してクエリを実行します。誤りの内容はpg_hint_plan.parse_messagesで指定したレベルでサーバログに記録されます。
<ul>
<li>ヒント句名を間違っている。</li>
<li>オブジェクト名を空白で区切っていない。</li>
</ul>
</dd>
-<dt><h3>オブジェクト指定エラー</h3></dt>
+<dt>オブジェクト指定エラー</dt>
<dd>pg_hint_planは、ヒント句対象のオブジェクト指定に誤りがあった場合、pg_hint_planは正常に解析できたヒントのみを適用して、それ以外を無視します。誤りの内容はpg_hint_plan.parse_messagesで指定したレベルでサーバログに記録されます。
<ul>
</dd>
-<dt><h3>重複したヒント</h3></dt>
+<dt>重複したヒント</dt>
<dd>同じオブジェクトに対して同じグループのヒント句を重複して指定した場合は、各グループで最後に指定したヒント句を使用します。</dd>
-<dt><h3>ネストしたブロックコメント</h3></dt>
+<dt>ネストしたブロックコメント</dt>
<dd>pg_hint_planでは、ヒントを指定したブロックコメントにネストしたブロックコメントを含めることができません。ネストしたブロックコメントを含めた場合は、誤った記述に関する情報を出力しますがエラー終了しません。ヒントを無視してクエリを実行します。</dd>
-<dt><h3>メッセージの出力レベル</h3></dt>
+<dt>メッセージの出力レベル</dt>
<dd>ヒントに誤りがあった場合に出力されるメッセージのレベルは、基本的にはpg_hint_plan.parse_messagesに指定したレベルです。ただし、ヒント句に指定したオブジェクトの長さが識別子の最大長(デフォルトでは63バイト)を超えた際に切り詰めた場合は、NOTICEで出力します。</dd>
<h2>注意事項</h2>
-<dt><h3>プランナパラメータの影響</h3></dt>
+<dt>プランナパラメータの影響</dt>
<dd>FROM句の要素数が from_collapse_limit 以上または join_collapse_limit を超える場合には、結合順序のヒント句は正しく動作しません。また、FROM句の要素数が geqo_threshold 以上の場合は、結合順序のヒント句、および結合方式のヒント句は動作しません。ヒント句が使われるようにするには、これらのGUCパラメータの値を十分に大きくしてください。</dd>
-<dt><h3>適用不能なヒント</h3></dt>
+<dt>実行不能なプランを指定するヒント</dt>
<dd>ヒントで指定した結果正しく実行できない実行計画が生成される場合は、実行可能なプランに強制的に修正します。実行不能な実行計画例を以下に示します。
<ul>
<li>特殊な場合を除いた FULL OUTER JOINに対する Nested Loop。</li>
<li>検索条件にctidを指定しない場合の Tid Scan。</li>
</ul>
</dd>
-<dt><h3>ECPGにおける制限</h3></dt>
+<dt>ECPGにおける制限</dt>
<dd>ECPGで実装したアプリケーションから発行するクエリにヒントをコメントで指定した場合、実行計画を制御できません。これは、CプリプロセッサがCコードに変換するタイミングで、全てのブロックコメントを取り除いてしまうためです。ただし、EXECUTEコマンドで実行する動的SQLに含まれるコメントは使用可能です。</dd>
-<dt><h3>異なるヒントを与えた同一クエリの pg_stat_statements での扱い</h3></dt>
+<dt>異なるヒントを与えた同一クエリの pg_stat_statements での扱い</dt>
<dd>pg_stat_statements ではクエリIDの生成の際にコメントは無視されます。そのため与えているヒントが異なる同一のクエリは一つのクエリとして集計されます。</dd>
</dl>