pg_hint_plan 拡張は、SQL コメント内にヒントを直接埋め込むことで、クエリ オプティマイザーの実行計画選択をオーバーライドできます。
PolarDB for PostgreSQL (Compatible with Oracle) では、統計データに基づいて実行計画を選択するコストベースオプティマイザが採用されています。このオプティマイザーは一般的に適切な選択を行いますが、すべてのデータ関係を考慮することはできません。Grand Unified Configuration (GUC) 変数を設定すると、セッション全体の動作が変更されますが、pg_hint_plan は単一のクエリのみに適用され、他の処理には一切影響を与えません。
前提条件
開始する前に、以下の条件を満たしていることを確認してください。
PolarDB for PostgreSQL (Compatible with Oracle) クラスター
拡張の作成およびユーザーまたはデータベース設定の変更に十分な権限を持つデータベースユーザー
注意事項
Data Management Service (DMS) ではヒントコメントがサポートされていません。別のクライアントを使用してデータベースに接続してください。
pg_hint_plan はクエリ内の最初のコメントブロックのみを読み取ります。その後のコメントブロック内のヒントは無視されます。
ヒントの解析中、スキャナーは英字、数字、空白、アンダースコア (
_)、カンマ (,)、または括弧 (()) 以外の文字に到達すると停止します。pg_hint_plan ではオブジェクト名の比較が大文字小文字を区別します。
TBLを参照するヒントは、TBLのみに適用され、tblやTblには適用されません。クエリでテーブルエイリアスが使用されている場合、ヒントでは元のテーブル名ではなくエイリアスを使用してください。
制限事項
PL/pgSQL ストアドプロシージャ内で pg_hint_plan を使用する場合、以下の制限が適用されます。
ヒントが有効になるステートメントの種類は以下のとおりです。
SELECT、INSERT、UPDATE、DELETE(単一行クエリ)RETURN QUERY(複数行クエリ)EXECUTE QUERY(SQL ステートメントの実行)OPEN(カーソルのオープン)FOR(クエリ結果の走査)
各ヒントはクエリの先頭の単語直後に配置してください。それより前の位置に配置されたヒントは、対象のクエリに関連付けられません。
拡張のインストール
拡張を作成します。
CREATE EXTENSION pg_hint_plan;以下のいずれかの方法で拡張をロードします。
単一ユーザー向け:
ALTER USER <username> SET session_preload_libraries = 'pg_hint_plan';<username>をログインユーザー名に置き換えてください。特定のデータベース向け:
ALTER DATABASE <database_name> SET session_preload_libraries = 'pg_hint_plan';説明構成エラーによりログインできない場合は、別のユーザーまたは別のデータベースに接続し、パラメーターをリセットしてください。
ALTER USER <username> RESET session_preload_libraries; ALTER DATABASE <database_name> RESET session_preload_libraries;データベースクラスターの場合: クォータセンター に移動します。PolarDB PG Pg_hint_plan 使用 の行で、申請 をクリックします(操作 列)。
拡張が正常にロードされたことを確認します。
デバッグ出力を有効化します。
SET pg_hint_plan.debug_print TO on; SET pg_hint_plan.message_level TO notice;ヒント付きのテストクエリを実行します。
/*+Set(enable_seqscan 1)*/SELECT 1;以下の出力が表示された場合、拡張が正常にロードされたことを確認できます。
NOTICE: pg_hint_plan: used hint: Set(enable_seqscan 1)デバッグ出力を無効化します。
RESET pg_hint_plan.debug_print; RESET pg_hint_plan.message_level;
ヒントコメントの記述
pg_hint_plan のコメントは /*+ で始まり、*/ で終了します。各ヒントは、括弧付きのパラメーターを伴うヒント名から構成され、複数のヒントは可読性向上のため改行で区切って記述します。
/*+
HashJoin(a b)
SeqScan(a)
*/
EXPLAIN SELECT *
FROM pgbench_branches b
JOIN pgbench_accounts a ON b.bid = a.bid
ORDER BY a.aid;生成されるクエリプランは以下のとおりです。
QUERY PLAN
---------------------------------------------------------------------------------------
Sort (cost=31465.84..31715.84 rows=100000 width=197)
Sort Key: a.aid
-> Hash Join (cost=1.02..4016.02 rows=100000 width=197)
Hash Cond: (a.bid = b.bid)
-> Seq Scan on pgbench_accounts a (cost=0.00..2640.00 rows=100000 width=97)
-> Hash (cost=1.01..1.01 rows=1 width=100)
-> Seq Scan on pgbench_branches b (cost=0.00..1.01 rows=1 width=100)
(7 rows)ヒントの種類
スキャン方式ヒント
スキャン方式ヒントは、存在する場合はエイリアスによって識別される対象テーブルに対して特定のスキャン方式を強制します。
有効な対象:標準テーブル、継承テーブル、非ログテーブル、一時テーブル、システムテーブル
無効な対象:外部テーブル、テーブル関数、定数値ステートメント、共通テーブル式(CTE)、ビュー、サブクエリ
/*+
SeqScan(t1)
IndexScan(t2 t2_pkey)
*/
SELECT * FROM table1 t1 JOIN table2 t2 ON (t1.key = t2.key);結合方式ヒント
結合方式ヒントは、一連のテーブルに対して特定の結合アルゴリズムを強制します。
有効な対象:標準テーブル、継承テーブル、非ログテーブル、一時テーブル、外部テーブル、システムテーブル、テーブル関数、定数値コマンド、CTE
無効な対象:ビュー、サブクエリ
結合順序ヒント
結合順序ヒントは、テーブルが結合される順序を指定します。2 種類の構文形式がサポートされています。
Leading(t1 t2 t3)— 結合順序のみを指定し、各レベルでの方向を制約しません。Leading((t1 t2) t3)— 順序と方向の両方を指定します(ネストされた括弧は結合ペアを示します)。
/*+
NestLoop(t1 t2)
MergeJoin(t1 t2 t3)
Leading(t1 t2 t3)
*/
SELECT * FROM table1 t1
JOIN table2 t2 ON (t1.key = t2.key)
JOIN table3 t3 ON (t2.key = t3.key);この例では、以下のとおりです。
NestLoop(t1 t2)— t1 と t2 の間でネステッドループ結合を使用します。MergeJoin(t1 t2 t3)— (t1, t2) の結合結果と t3 の間でマージ結合を使用します。Leading(t1 t2 t3)— 3 つのテーブルを t1 → t2 → t3 の順で結合します。
行数補正ヒント
行数補正ヒントは、結合結果に対してオプティマイザーが使用する行数推定値を上書きします。これは、オプティマイザーの統計情報が不正確な場合に有効です。
/*+ Rows(a b #10) */ SELECT ...; -- 結合結果を正確に 10 行に設定
/*+ Rows(a b +10) */ SELECT ...; -- 推定行数に 10 を加算
/*+ Rows(a b -10) */ SELECT ...; -- 推定行数から 10 を減算
/*+ Rows(a b *10) */ SELECT ...; -- 推定行数を 10 倍に設定並列実行ヒント
並列実行ヒントは、クエリの並列処理の次数を制御します。
有効な対象:標準テーブル、継承テーブル、非ログテーブル、システムテーブル。ビューの内部テーブルは、実際の名前またはエイリアスで指定できます。
無効な対象:外部テーブル、定数句、CTE、ビュー、サブクエリ
例 1:結合における 2 つのテーブルの並列処理を設定します。
EXPLAIN /*+ Parallel(c1 3 hard) Parallel(c2 5 hard) */
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)
Workers Planned: 3
-> Parallel Seq Scan on c1 (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)
Workers Planned: 5
-> Parallel Seq Scan on c2 (cost=0.00..1.59 rows=59 width=4)例 2:単一テーブル集約の並列処理を設定します。
EXPLAIN /*+ Parallel(tl 5 hard) */ SELECT sum(a) FROM tl;出力:
QUERY PLAN
-----------------------------------------------------------------------------------
Finalize Aggregate (cost=693.02..693.03 rows=1 width=8)
-> Gather (cost=693.00..693.01 rows=5 width=8)
Workers Planned: 5
-> Partial Aggregate (cost=693.00..693.01 rows=1 width=8)
-> Parallel Seq Scan on tl (cost=0.00..643.00 rows=20000 width=4)GUC パラメーター ヒント
GUC パラメーター ヒントは、クエリプラン生成時のみ GUC パラメーターの値を変更します。この変更は他のステートメントには影響しません。同一の GUC パラメーターが複数回出現した場合、最後に指定された値が有効になります。
/*+ Set(random_page_cost 2.0) */
SELECT * FROM table1 t1 WHERE key = 'value';ヒント リファレンス
以下の表に、サポートされるすべてのヒントフォーマットを示します。角括弧 [ ] で囲まれた項目は省略可能です。
| 種類 | フォーマット | 説明 |
|---|---|---|
| スキャン方式 | SeqScan(table) | テーブルに対してシーケンシャルスキャンを強制します。 |
TidScan(table) | テーブルに対して TID スキャンを強制します。 | |
IndexScan(table [index...]) | インデックススキャンを強制します。必要に応じて使用するインデックスを指定できます。 | |
IndexOnlyScan(table [index...]) | インデックスのみスキャンを強制します。必要に応じて使用するインデックスを指定できます。 | |
BitmapScan(table [index...]) | ビットマップ索引スキャンを強制します。必要に応じて使用するインデックスを指定できます。 | |
NoSeqScan(table) | シーケンシャルスキャンを禁止します。 | |
NoTidScan(table) | TID スキャンを禁止します。 | |
NoIndexScan(table) | インデックススキャンを禁止します。 | |
NoIndexOnlyScan(table) | インデックスのみスキャンを禁止します。 | |
NoBitmapScan(table) | ビットマップ索引スキャンを禁止します。 | |
| 結合方式 | NestLoop(table table [table...]) | ネステッドループ結合を強制します。 |
HashJoin(table table [table...]) | ハッシュ結合を強制します。 | |
MergeJoin(table table [table...]) | マージ結合を強制します。 | |
NoNestLoop(table table [table...]) | ネステッドループ結合を禁止します。 | |
NoHashJoin(table table [table...]) | ハッシュ結合を禁止します。 | |
NoMergeJoin(table table [table...]) | マージ結合を禁止します。 | |
| 結合順序 | Leading(table table [table...]) | 結合順序を指定します(順序のみ、方向制約なし)。 |
Leading(<join pair>) | ネストされた括弧を使用して結合順序と方向を指定します。 | |
| 行数補正 | Rows(table table [table...] correction) | 結合の行数推定値を補正します。補正方法: #<n>(設定)、+<n>(加算)、-<n>(減算)、*<n>(乗算)。 |
| 並列クエリ | Parallel(table <# of workers> [soft|hard]) | 指定されたテーブルの並列スキャンを制御します。<# of workers> を 0 に設定すると並列実行が無効になります。soft(デフォルト)では max_parallel_workers_per_gather を調整し、最終的な並列処理の次数はオプティマイザーが決定します。hard では指定された次数を強制します。 |
PX(<# of workers>) | ノード間並列実行 の並列処理の次数を指定します。 | |
NoPX() | クエリに対するノード間並列実行を無効化します。 | |
| GUC パラメーター | Set(GUC-param value) | クエリプラン生成中に GUC パラメーターを指定された値に設定します。 |
ノード間並列実行シナリオでは:
行数補正ヒントはサポートされていません。
結合方式ヒントは、2 つのテーブル間の結合にのみ適用されます。
結合順序ヒントは、すべてのテーブルの全体的な結合順序のみを指定できます。