PolarDB for PostgreSQL(Oracle 互換)の「概要(Outline)」機能では、アプリケーションの SQL を変更せずに、PREPARE 文を特定の実行計画に固定できます。統計情報の更新、バージョンアップ、またはパラメーター束縛の変更後にオプティマイザーが非最適な計画を選択した場合、既知の良好な実行計画を「概要」で固定することで、パフォーマンスの劣化を防止できます。
「概要」は SQL プラン管理(SPM)の一部です。「概要」では固定実行計画のみがサポートされ、進化した実行計画(evolved execution plan)はサポートされません。
前提条件
開始する前に、クォータセンターで polar_outline ホワイトリストを申請済みであることを確認してください。[操作] 列で、polardb_pg_polar_outline の横にある [申請] をクリックします。
拡張機能の設定
polar_outline拡張機能を作成します:CREATE EXTENSION polar_outline;すべての「概要」関数および関係は
polar_outlineスキーマ内に格納されます。スキーマを検索パスに追加し、「概要」関数をスキーマプレフィックスなしで呼び出せるようにします:
SET search_path TO "$user", public, polar_outline;固定計画の適用を有効化します:
SET polar_outline.use_stored_plan TO ON;
テストデータの準備
以下のステートメントを実行して、t という名前のテーブルを作成し、データを挿入します:
CREATE TABLE t(a INT, b INT);
INSERT INTO t SELECT i, i FROM generate_series(1, 1000) i;テーブル内のデータを更新して、オプティマイザーが正確な統計情報を使用できるようにします:
ANALYZE t;PREPARE 文を実行します:
PREPARE test AS SELECT * FROM t WHERE a=$1;このテストデータは、本セクションの例でのみ使用されます。実際のビジネス要件に応じて、ステートメントを適宜修正してください。
「概要」機能は、キャプチャ対象の実行計画を制御するためのヒントワードを提供します。ステートメントにこのヒントワードを含めて実行すると、そのステートメントの実行計画がキャプチャされます。その後、ヒントワードを含めずに同じステートメントを実行しても、キャプチャされた実行計画に基づいて実行されます。
実行計画のキャプチャと固定
「概要」機能では、PREPARE 文の実行計画のみを固定できます。
状況に応じて、以下のいずれかのキャプチャ方法を選択してください:
| 状況 | 方法 |
|---|---|
| 単一のステートメントの計画を固定する場合 | polar_outline_create 関数を直接呼び出す(推奨) |
| 複数のステートメントの計画を一度にキャプチャする場合 | capture_plan フラグを使用する |
方法 1:polar_outline_create の呼び出し(推奨)
polar_outline_create は、単一の EXECUTE 呼び出しに対して、実行計画のキャプチャと固定を 1 回の処理で実行します。
SELECT polar_outline_create('EXECUTE test(100)');期待される出力:
polar_outline_create
----------------------
t
(1 row)方法 2:capture_plan フラグの使用
単一のセッション内で複数のステートメントの計画をキャプチャする必要がある場合に使用します。
この方法ではプランキャッシュが生成されます。
計画キャプチャを有効化します:
SET polar_outline.capture_plan TO ON;計画を固定したい各ステートメントを実行します:
EXECUTE test(100);すべての計画のキャプチャが完了したら、計画キャプチャを無効化します:
SET polar_outline.capture_plan TO OFF;
プラン切り替えによるクエリリライト
PolarDB による SQL クエリのリライト後にパフォーマンスの問題が発生した場合、「概要」機能を用いて SQL クエリをリライトできます。
切り替える 2 つの実行計画は、セマンティクス上等価である必要があります。等価でない計画間で切り替えると、不正な結果セットが返される可能性があります。
以下の例では、ハッシュ結合(Hash Join)を使用する SQL1 の実行計画を、より効率的なネステッドループ結合(Nested Loop)+ラテラル結合(lateral join)を使用する SQL2 の実行計画に置き換えます。
SQL1 — 元のクエリ:
select t.a, t2.avg_b
from t join (select avg(b) as avg_b, a
from t2
group by a) t2
on t2.a = t.a and t.c < $1
order by t.a;SQL2 — セマンティクスが等価なリライト済みクエリ:
select t.a, t2.avg_b
from t join lateral (select avg(b) as avg_b
from t2
where t2.a = t.a) as t2
on t.c < $1
order by t.a;テストテーブルを準備します:
CREATE TABLE t(a int, b int, c int); INSERT INTO t SELECT i % 100000, i, i FROM generate_series(1, 1000000) i; CREATE TABLE t2 AS SELECT * FROM t; CREATE INDEX ON t(c); CREATE INDEX ON t2(a); ANALYZE t, t2;両方のクエリの実行計画をキャプチャします:
PREPARE s1 AS SELECT t.a, t2.avg_b FROM t JOIN (SELECT avg(b) AS avg_b, a FROM t2 GROUP BY a) t2 ON t2.a = t.a AND t.c < $1 ORDER BY t.a; PREPARE s2 AS SELECT t.a, t2.avg_b FROM t JOIN LATERAL (SELECT avg(b) AS avg_b FROM t2 WHERE t2.a = t.a) AS t2 ON t.c < $1 ORDER BY t.a; SELECT polar_outline.polar_outline_create('EXECUTE s1(5)'); SELECT polar_outline.polar_outline_create('EXECUTE s2(5)');両方の呼び出しは成功時に
tを返します。s1の実行計画を、s2の実行計画に切り替えます。入力パラメーターは、それぞれの実行計画の「概要」内 ID です:SELECT polar_outline.polar_outline_switch(1, 2);EXPLAINを使用して、s1がネステッドループ計画を使用していることを確認します:EXPLAIN (COSTS FALSE) EXECUTE s1(5);切り替え後の期待される出力:
QUERY PLAN ------------------------------------------------------- Sort Sort Key: t.a -> Nested Loop -> Index Scan using t_c_idx on t Index Cond: (c < $1) -> Aggregate -> Bitmap Heap Scan on t2 Recheck Cond: (a = t.a) -> Bitmap Index Scan on t2_a_idx Index Cond: (a = t.a) (10 rows)s2の概要を削除します。これは、もはや必要ありません:SELECT polar_outline.polar_outline_delete(2);
パラメーター
すべてのパラメーターは polar_outline 名前空間に属します。SET polar_outline.<parameter> TO <value>; を使用して設定します。
| パラメーター | 値 | 説明 |
|---|---|---|
use_stored_plan | ON、OFF | 固定された計画の適用を制御します。ON に設定すると保存済みの計画が使用され、OFF に設定するとオプティマイザーが自由に計画を選択できます。 |
capture_plan | ON、OFF | 「概要」機能がステートメント実行時に自動的に計画をキャプチャするかどうかを制御します。有効化するとプランキャッシュが生成されます。 |
log_usage | none、debug、debug1~debug5、log、info、notice、warning | 「概要」のログ出力の詳細度を設定します。none ではログ出力を無効化します。debug~debug5 は、トラブルシューティング向けに段階的に詳細度が増します。log、info、notice、warning は、対応する PostgreSQL のログ重大度レベルにマップされます。 |
注意事項
「概要」機能では、PREPARE 文の実行計画のみを固定できます。アドホッククエリはサポートされません。
ステートメントに埋め込まれたヒントワードにより、その実行に対する計画がキャプチャされます。その後、ヒントワードを含めずに同一のステートメントを実行しても、キャプチャされた計画が引き続き使用されます。
例で使用されるテストデータはあくまで説明用です。ワークロードに合わせてテーブル定義およびパラメーター値を調整してください。