すべてのプロダクト
Search
ドキュメントセンター

ApsaraDB RDS:pg_hint_plan拡張機能を使用したクエリプランのカスタマイズ

最終更新日:Dec 09, 2024

このトピックでは、ApsaraDB RDS for PostgreSQLのpg_hint_plan拡張機能について説明します。 この拡張機能を使用して、ApsaraDB RDS for PostgreSQLインスタンスのSQL文の実行計画を変更するヒントを追加できます。

前提条件

  • RDSインスタンスはPostgreSQL 10以降を実行します。

    説明

    pg_hint_plan拡張機能を作成できない場合は、RDSインスタンスのマイナーエンジンバージョンを更新する必要があります。 詳細については、「ApsaraDB RDS For PostgreSQLインスタンスのマイナーエンジンバージョンの更新」をご参照ください。

  • pg_hint_planは、RDSインスタンスのshared_preload_librariesパラメーターの値に追加されます。

    shared_preload_librariesパラメーターの値にpg_hint_planを追加する方法の詳細については、「ApsaraDB RDS For PostgreSQLインスタンスのパラメーターの変更」をご参照ください。

  • この拡張機能は、データ管理 (DMS) ではサポートされません。 別のクライアントを使用してRDSインスタンスに接続することを推奨します。

背景情報

PostgreSQLは、静的ルールではなくデータ統計に基づいて機能するコストベースのオプティマイザを使用します。 オプティマイザーは、各SQL文のすべての可能な実行プランのコストを評価し、コストが最も低い実行プランを選択します。 しかし、オプティマイザは、データ間の可能な内部関係を考慮しない。 したがって、最終的な実行計画は最良の計画ではない可能性があります。 pg_hint_plan拡張機能を使用して、SQL文にヒントを追加できます。 ヒントは、SQL文の実行方法を指定します。 これにより、SQL文の実行計画を最適化できます。

基本的な使用方法

ヒントは、スラッシュ、アスタリスク、プラス記号 (/* +) で始まり、アスタリスクとスラッシュ (*/) で終わります。 ヒントは、ヒント名とパラメータで構成されます。 ヒント名はパラメータの前にあります。 パラメータは括弧 () で囲まれ、スペースで区切られています。 読みやすくするために、各ヒントを改行で区切ることができます。

例:

この例では、HashJoinヒントは、pgbench_accountsテーブルをスキャンするためにSeqScanメソッドを使用することを指定します。

 /*+
    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)

ヒントテーブル

ヒントを使用して、SQL文の実行計画を最適化できます。 ただし、これはSQL文が編集可能な場合にのみ便利です。 SQL文を編集できない場合は、hint_plan.hintsという名前のテーブルにヒントを配置できます。 hint_plan.hintsテーブルには、次の表に示す列が含まれています。

説明

デフォルトでは、pg_hint_plan拡張機能を作成するユーザーには、hint_plan.hintsテーブルに対する権限があります。 hint_plan.hintsテーブルのヒントは、pg_hint_plan拡張機能を使用して追加したヒントよりも優先されます。

項目

説明

id

ヒントのID。 IDは一意であり、自動的に生成されます。

norm_query_string

ヒントを追加するSQL文と一致するパターン。 SQL文の定数は、ワイルドカード (?) に置き換える必要があります。 スペースはパターンの重要な部分です。

application_name

ヒントが適用されるアプリケーションの名前。 このパラメーターが空の場合、ヒントはすべてのアプリケーションに適用されます。

ヒント

ヒントを含むコメント。 コメントマークを含める必要はありません。

例:

INSERT INTO hint_plan.hints(norm_query_string, application_name, hints)
    VALUES (
        'EXPLAIN (COSTS false) SELECT * FROM t1 WHERE t1.id = ?;',
        '',
        'SeqScan(t1)'
    );
INSERT 0 1
postgres=# UPDATE hint_plan.hints
postgres-#    SET hints = 'IndexScan(t1)'
postgres-#  WHERE id = 1;
UPDATE 1
postgres=# DELETE FROM hint_plan.hints
postgres-#  WHERE id = 1;
DELETE 1

ヒントタイプ

ヒントは、実行計画への影響に基づいて、次のタイプに分類されます。

  • スキャン方法のヒント

    このタイプのヒントは、指定されたテーブルをスキャンするために使用されるメソッドを指定します。 指定されたテーブルにエイリアスがある場合、pg_hint_plan拡張機能はエイリアスに基づいてテーブルを識別します。 サポートされているスキャン方法には、SeqScanIndexScan、およびNoSeqScanがあります。

    スキャンメソッドのヒントは、通常テーブル、継承テーブル、未ログテーブル、一時テーブル、およびシステムテーブルで有効です。 スキャンメソッドのヒントは、外部テーブル、テーブル関数、定数の値が指定されているステートメント、ユニバーサル式、ビュー、およびサブクエリでは無効です。

    例:

    /*+
        SeqScan(t1)
        IndexScan(t2 t2_pkey)
     */
    SELECT * FROM table1 t1 JOIN table table2 t2 ON (t1.key = t2.key);
  • 結合メソッドのヒント

    このタイプのヒントは、指定されたテーブルを結合するために使用されるメソッドを指定します。

    結合メソッドのヒントは、通常のテーブル、継承テーブル、未ログテーブル、一時テーブル、外部テーブル、システムテーブル、テーブル関数、定数の値が指定されているステートメント、および普遍的な式で有効です。 ビューとサブクエリでは、結合メソッドのヒントが無効です。

  • 参加注文のヒント

    このタイプのヒントは、2つ以上のテーブルを結合する順序を指定します。 次のいずれかの方法を使用して、結合順序を指定するヒントを指定できます。

    • 各結合レベルで方向を制限することなく、指定したテーブルを結合する順序を指定します。

    • 指定したテーブルを結合する順序と、各結合レベルでの方向を指定します。

    例:

    /*+
        NestLoop(t1 t2)
        MergeJoin(t1 t2 t3)
        Leading(t1 t2 t3)
     */
    SELECT * FROM table1 t1
        JOIN table table2 t2 ON (t1.key = t2.key)
        JOIN table table3 t3 ON (t2.key = t3.key);
  • 行番号修正のヒント

    このタイプのヒントは、オプティマイザによって引き起こされる行番号エラーを修正します。

    例:

    /*+ Rows(a b #10) */ SELECT... ;     //Set the row number to 10. 
    /*+ Rows(a b +10) */ SELECT... ;     //Increase the row number by 10. 
    /*+ Rows(a b -10) */ SELECT... ;     //Decrease the row number by 10. 
    /*+ Rows(a b *10) */ SELECT... ;     //Increase the row number by 10 times. 
  • 並列実行のヒント

    このタイプのヒントは、SQL文を並列に実行するために使用されるプランを指定します。

    並列実行のヒントは、通常テーブル、継承テーブル、未ログテーブル、およびシステムテーブルで有効です。 並列実行のヒントは、外部テーブル、定数の値が指定されている句、ユニバーサル式、ビュー、およびサブクエリでは無効です。 ビューの内部テーブルは、その実名またはエイリアスに基づいて指定できます。

    次の例は、各テーブルでSQL文を異なる方法で実行する方法を示しています。

    • 例 1:

      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パラメーターの値は、期待どおりの効果を得るのに役立ちます。 ただし、指定されたヒントが他のSQL文の実行プランと競合する場合、これは適用されません。 GUCパラメーターを複数回設定すると、最新の値が有効になります。

    例:

    /*+ Set(random_page_cost 2.0) */
    SELECT * FROM table1 t1 WHERE key = 'value';

次の表に、pg_hint_plan拡張機能でサポートされているすべてのヒントを示します。

タイプ

Format

説明

スキャン方法のヒント

SeqScan (テーブル)

シーケンシャルスキャンを指定します。

TidScan (テーブル)

TIDスキャンを指定します。

IndexScan (テーブル [インデックス...])

インデックススキャンを指定します。 インデックスを指定できます。

IndexOnlyScan (テーブル [インデックス...])

インデックスのみのスキャンを指定します。 インデックスを指定できます。

BitmapScan (テーブル [インデックス...])

ビットマップスキャンを指定します。

NoSeqScan (テーブル)

シーケンシャルスキャンを禁止します。

NoTidScan (テーブル)

TIDスキャンを禁止します。

NoIndexScan (テーブル)

インデックススキャンを禁止します。

NoIndexOnlyScan (テーブル)

インデックススキャンを禁止します。 テーブルのみがスキャンされます。

NoBitmapScan (テーブル)

ビットマップスキャンを禁止します。

結合メソッドのヒント

NestLoop (テーブルテーブル [テーブル...])

ネストされたループ結合を指定します。

HashJoin (テーブルテーブル [テーブル...])

ハッシュ結合を指定します。

MergeJoin (テーブルテーブル [テーブル...])

マージ結合を指定します。

NoNestLoop (テーブルテーブル [テーブル...])

ネストされたループ結合を禁止します。

NoHashJoin (テーブルテーブル [テーブル...])

ハッシュ結合を禁止します。

NoMergeJoin (テーブルテーブル [テーブル...])

マージ結合を禁止します。

参加注文のヒント

リーディング (テーブルテーブル [テーブル...])

結合順序を指定します。

リーディング (<参加ペア>)

結合の順序と方向を指定します。

行番号修正のヒント

行 (テーブルテーブル [テーブル...] 修正)

指定したテーブルから取得した結合結果の行番号を修正します。 #<n>+ <n>-<n>* <n> の演算子がサポートされています。 <n> 演算子はstrtod関数でサポートされています。

並列実行のヒント

Parallel (テーブル <# of workers> [soft | hard])

指定されたテーブルの並列実行を指定または禁止します。 <worker#> パラメーターは、必要な作業プログラムの数を指定します。 値0は、並列実行が禁止されることを示す。

3番目のパラメーターをsoftに設定すると、max_parallel_workers_per_gatherパラメーターの値のみが変更され、その他のパラメーターはオプティマイザによって指定されます。 3番目のパラメーターをhardに設定すると、関連するすべてのパラメーターの値が変更されます。 3番目のパラメーターのデフォルト値はsoftです。

GUCパラメータ設定のヒント

セット (GUC-param値)

オプティマイザの実行時のGUCパラメーターの値を指定します。

詳細については、PostgreSQL Webサイトをご覧ください。