Amazon Web Services ブログ
Amazon Aurora PostgreSQL でのクエリ計画管理のユースケース
このブログの投稿は一連の投稿の 2 回目です。前回のブログ記事では、SQL ステートメントの実行計画に回帰を引き起こす可能性があるその他の変更の中で、安定かつ一貫したデータベースパフォーマンスの必要性について説明しました。また、PostgreSQL と互換性のある Amazon Aurora のクエリ計画管理 (QPM) が、計画安定性と計画適応性の問題を克服できるようにする方法も述べています。
この記事では、引き続き Aurora PostgreSQL QPM の機能について説明します。特に、これらの機能によって、さまざまな高度なユースケースに対して計画安定性と適応性を実現する方法についてお話します。
ユースケース #1: QPM 手動取得による計画安定性と適応性の支援
最初のユースケースでは、QPM が計画安定性を確保する方法について例を挙げて説明します。次に、前回の記事 Aurora PostgreSQL クエリ計画管理の概要で説明した変更を行います。QPM を使用しない場合は、これらの変更により計画の回帰が生じる可能性があります。
ほとんどの場合、自動計画取り込みを使用するように QPM を設定して、2 回以上実行されるすべてのステートメントを取得することもできます。ただし、手動で指定した特定のステートメントセットの計画を取得することもできます。そのためには、デフォルトに capture_plan_baselines = off
を設定します。セッションレベルでは、capture_plan_baselines = manual
を設定します。設定の仕方については後で説明します。
- 手動計画取り込みを有効にして、目的の SQL ステートメントの実行計画を手動で取得するように QPM に指示します。
- QPM がクエリ計画を取得できるように、クエリ説明計画を実行します (説明計画の以下の出力は、簡潔にするために省略されています)。
- 目的の SQL ステートメントの実行計画を取得した後で、計画の手動取得を無効にします。
- 以前実行されたクエリで取得したクエリ計画を表示します。テーブル
apg_plan_mgmt.dba_plans
のplan_outline
列には、SQL の全体計画が表示されます。簡潔にするため、plan_outline
はここには示されません。代わりに、前述の説明計画のplan_hash_value
がapg_plan_mgmt.dba_plans
クエリ出力のplan_hash
と比較されます。 - 管理ステートメントに承認取得計画または優先取得計画を使用するようにクエリオプティマイザに指示するには、パラメータ
apg_plan_mgmt.use_plan_baselines
を true に設定します。 - 説明計画の出力を表示して、QPM 承認計画がクエリオプティマイザによって使用されていることを確認します。
- 計画設定を変更し、クエリオプティマイザに新しい計画を生成するために、
pgbench_history
テーブルの「mtime」列に新しいインデックスを作成します。 - 説明計画の出力を表示して、QPM が新しい計画を検出した場合でも、承認計画を使用し計画安定性を維持していることを確認します。
- 以下の SQL クエリを実行して、新しい計画と計画のステータスを表示します。計画安定性を確保するために、QPM は管理クエリに対して新しく生成されたすべての計画を未承認計画として QPM に保存します。次の出力は、2 つの異なる
plan_hash
値によって示されるように、同じ管理ステートメントに対して 2 つの異なる説明計画が保存されていることを表します。新しい実行計画は費用を最小限に (承認計画よりも低く) 抑えられますが、QPM は計画安定性を維持するために未承認計画を無視し続けます。テーブルapg_plan_mgmt.dba_plans
のplan_outline
列には、SQL の全体計画が表示されます。簡潔にするために、plan_outline
はここには示されません。代わりに、前述の説明計画のplan_hash_value
がapg_plan_mgmt.dba_plans
クエリ出力のplan_hash
と比較されます。以下は、QPM による計画適応性の例です。この例では、最小速度向上係数に基づいて未承認計画を評価します。ステートメントに対して最も優れた承認計画よりも 10% 以上速い、取得済みの未承認計画を承認します。詳細については、Aurora のドキュメント計画パフォーマンスの評価を参照してください。
QPM が速度係数に基づいて計画を評価した後、計画のステータスが承認済みに変わります。この時点で、オプティマイザは管理ステートメントに計画をすぐ選択できるようになります。
ユースケース #2。pg_hint_plan を使用して QPM で計画を修正
場合によっては、クエリオプティマイザがクエリに最適な実行計画を生成しないことがあります。この問題を解決するアプローチの 1 つはアプリケーションコードにクエリのヒントを含めることですが、このアプローチはアプリケーションを脆弱にし、保守を難しくするため、広くお勧めされていません。一部の場合、サードパーティー製のアプリケーションによって生成されているため、SQL のヒントを得られないことがあります。ここでは、ヒントを使用してクエリオプティマイザを制御する方法を示しています。ただしこれは、アプリケーションコードにヒントを追加することなく、ヒントを削除して QPM が目的の計画を実行できるようにする方法です。
このために、PostgreSQL ユーザーは pg_hint_plan
拡張機能を使用して、「scan method」、「join method」、「join order」、「row number correction」などのディレクティブをオプティマイザに提供することができます。 結果として生じる計画は、QPM によって、上書きを選択した GUC パラメータ (work_mem
など) とともに保存されます。 QPM は GUC パラメータの上書きを記憶し、計画を再作成するときにそれらを使用します。pg_hint_plan
拡張機能のインストール方法と使い方の詳細については、pg_hint_plan のドキュメントを参照してください。
ヒントを使用して生成した計画を修正するための QPM 手順
pg_hint_plan
を使用した操作は、ヒントを追加するためにクエリを修正できない場合に非常に便利です。この例では、サンプルのクエリを使用して、管理ステートメントにヒントを追加し、必要な実行計画を生成します。次に、この実行計画を元の未修正ステートメントに関連付けます。
手順の詳細は以下のとおりです。
- 計画の取り込みが無効になっていないか確認してください。
- 使用するヒントでクエリを実行します。次の例では、「HashJoin」ヒントを使用します。これは、オプティマイザが HashJoin で join メソッドを選択するためのディレクティブです。ヒントがないクエリの元の計画は次のとおりです。
入れ子のループに必要な計画は次のとおりです。
-
pg_hint_plan
と手動計画取り込みを有効にします。 - 使用したいヒントでクエリを実行します。次の例では、HashJoin (a、b) ヒントを使用します。これは、オプティマイザがハッシュ結合アルゴリズムを使用してテーブル a からテーブル b に結合するためのディレクティブです。ハッシュ結合で必要な計画は次のとおりです。
- 計画 1139293728 が取得されたことを確認して、計画のステータスを書き留めます。取得した計画と計画のステータスを表示します。
- 必要に応じて、計画を承認します。この場合、ステートメント 356104612 用に保存された最初で唯一の計画であるため、承認計画として保存されました。 このステートメントにすでに承認計画のベースラインがある場合、この計画は未承認計画として保存されています。一般的に、ステートメントの既存の計画をすべて却下してから特定の計画を 1 つ承認するために、次のように apg_plan_mgmt.set_plan_status を 2 回呼び出すことができます。
- ヒントを削除し、手動取得をオフにし、
use_plan_baselines
をオンにして、目的の計画がヒントなしで使用中であることを確認します。
ユースケース 3: QPM 管理計画のエクスポートとインポートを使用して QPM 管理計画をグローバルにデプロイ
大企業のお客様は、多くの場合、アプリケーションとデータベースをグローバルにデプロイしています。また、アプリケーションデータベースごとに複数の環境 (Dev、QA、Staging、UAT、Preprod、および Prod) を維持しています。ただし、特定の AWS リージョン内の各データベースと各データベース環境で実行計画を手動で管理すると、面倒で時間がかかる場合があります。
QPM は、QPM 管理計画をあるデータベースから別のデータベースにエクスポートおよびインポートするためのオプションを備えています。このオプションを使用すると、クエリの実行を一元的に管理し、データベースをグローバルにデプロイできます。この機能は、preprod データベースで一連の計画を調査し、計画が適切に機能していることを確認してから、本稼働データベースに読み込むシナリオに役立ちます。
QPM 管理計画をあるデータベースから別のデータベースに移行する手順は、次のとおりです。詳細については、Aurora のドキュメントエクスポートおよびインポート計画を参照してください。
- ソースシステムから QPM 管理計画をエクスポートします。
このために、承認された DB ユーザーは 優先実行計画があるソースデータベースから、apg_plan_mgmt.plans
テーブルの任意のサブセットを別のテーブルにコピーできます。そのユーザーはpg_dump
コマンドを使用して、コピーしたサブセットを保存することができます。pg_dump
の詳細については、PostgreSQL のドキュメントから pg_dump を参照してください。 - ターゲットシステムに QPM 管理計画をインポートします。
- ターゲットシステムで、
apg_plan_mgmt.plans
テーブルの任意のサブセットを別のテーブルにコピーしてから、pg_dump
コマンドを使用してそれを保存します。これは、ソースシステムの新しい計画をインポートする前に、ターゲットシステムの既存の管理計画を保存するオプションの手順です。 - ステップ 1 で
pg_dump
tar 形式のアーカイブを使用したことを前提としています。pg_restore
コマンドを使用して、.tar ファイルを新しいテーブル (plan_copy) にコピーします。pg_restore
の詳細については、PostgreSQL のドキュメントから pg_restore を参照してください。 - 新しいテーブルを
apg_plan_mgmt.plans
テーブルとマージします。 - 管理計画を共有メモリに再度読み込み、一時計画テーブルを削除します。
SELECT apg_plan_mgmt.reload();
— 新しい計画で共有メモリを更新します。DROP TABLE plans_copy; --
一時計画テーブルを削除します。
まとめ
この記事では、Aurora PostgreSQL QPM の高度なユースケースについて説明しました。その 1 つが、QPM と pg_hint_plan
の統合方法です。これにより、オプティマイザがヒントを使用して最適な実行計画を生成することができます。オプティマイザは、変更できない SQL ステートメント (商用の市販アプリケーションの一部であるステートメントなど) に対しても最適な実行計画を生成できます。
その他のユースケースには、QPM のエクスポートおよびインポート機能が含まれます。これにより、実行計画を一元管理し、グローバルにデプロイできます。集中管理とグローバルなデプロイにより、複数の環境と AWS リージョンにまたがる複数のデータベースに渡って既知の実行計画をすばやくデプロイできます。
これまで QPM の重要なユースケースをいくつか取り上げました。さらに、QPM を使用して、持続可能で最適なデータベースパフォーマンスを達成するためにも同様に重要な他のユースケースを実装できます。QPM の詳細については、Aurora のドキュメントから Aurora PostgreSQL のクエリ実行計画の管理を参照してください。
著者について
Sameer Malik は、アマゾンウェブサービスのプリンシパルデータベースソリューションアーキテクトです。
Jim Finnerty は、アマゾンウェブサービスの Aurora PostgreSQL のプリンシパルソフトウェアエンジニアです。