PolarDB for PostgreSQL (Compatible with Oracle) と は、分析クエリのためのエラスティックパラレルクエリをサポートし、ハイブリッドトランザクション/分析処理 (HTAP) 機能を提供します。このトピックでは、エラスティックパラレルクエリを使用して分析クエリのパフォーマンスを向上させる方法について説明します。
仕組み
クエリがエラスティックパラレルクエリを使用すると、クエリコーディネーター (QC) ノードは実行計画を複数のシャードに分割し、それらをパラレル実行 (PX) ノードにルーティングします。各 PX ノードは割り当てられた計画シャードを実行し、部分的な結果を QC ノードに返します。QC ノードはそれらを集約して最終的な結果を生成します。QC ノードは、最初のクエリリクエストを受信するノードです。
図では、RO1 が QC ノードです。クエリを受信し、実行計画を分割し、計画シャードを 3 つの PX ノード (RO2、RO3、RO4) にルーティングします。各 PX ノードは計画シャードを実行し、PolarFS 共有ストレージから必要なデータブロックを読み取り、結果を QC ノードに返します。QC ノードは結果を集約し、最終的な出力を返します。
注意事項
大量のリソースを消費するため、頻度の低い分析クエリにのみ適しています。
詳細な制御
- システムレベル:パラメーターを使用して、すべてのセッションのすべてのクエリに対してエラスティックパラレルクエリを有効にするかどうかを制御します。
- セッションレベル:
ALTER SESSIONまたはセッションレベルの GUC パラメーターを使用して、現在のセッションの機能を制御します。 - クエリレベル:ヒントを使用して、特定のクエリをパラレルで実行するかどうかを指定します。
パラメーター
デフォルトでは、PolarDB for PostgreSQL (Compatible with Oracle) と ではエラスティックパラレルクエリは無効になっています。この機能を使用するには、次のパラメーターを設定します:
| パラメーター | 説明 |
| polar_cluster_map | ご利用の PolarDB for PostgreSQL (Compatible with Oracle) および クラスター内のすべての読み取り専用ノードの名前をリストします。このパラメーターは、新しい読み取り専用ノードを追加すると自動的に更新されます。 説明 このパラメーターは、マイナーカーネルバージョン 1.1.20 (2022 年 1 月リリース) 以前で作成されたクラスターでのみ利用可能です。 |
| polar_px_nodes | エラスティックパラレルクエリに参加する読み取り専用ノードを指定します。デフォルトでは空であり、すべての読み取り専用ノードが使用されることを意味します。ノードはカンマ区切りのリストで指定できます。例: |
| polar_px_enable_replay_wait | PolarDB for PostgreSQL (Compatible with Oracle) と では、プライマリノードと読み取り専用ノードの間にレプリケーション遅延が発生することがあります。CREATE TABLE のような DDL 文がプライマリノードで実行されると、読み取り専用ノードは対応する WAL ログをリプレイしてからでないと新しいテーブルは可視になりません。もし polar_px_enable_replay_wait を on に設定すると、エラスティックパラレルクエリは強力な整合性を強制します。パラレルクエリが読み取り専用ノードにルーティングされると、そのノードはクエリが開始される前に記録された最新のエントリまでログをリプレイする必要があります。その後でクエリを実行します。レプリケーションレイテンシーが高い場合、読み取り専用ノードは最新の DDL レコードを参照できない可能性があります。 このパラメーターは、特定のデータベースロールに対して有効にできます。 |
| polar_px_max_workers_number | 単一ノード上のエラスティックパラレルクエリに対する PX ワーカプロセスの最大数を設定します。デフォルトは 30 です。ノード上のすべてのセッションの PX ワーカプロセスの合計数は、この値を超えることはできません。 |
| polar_enable_px | エラスティックパラレルクエリを有効にするかどうかを指定します。デフォルトは off です。 |
| polar_px_dop_per_node | 現在のセッションの並列度 (DoP) を設定します。デフォルトは 1 です。CPU コアの総数に設定することを推奨します。このパラメーターを N に設定すると、セッションは参加する各ノードで N 個の PX ワーカプロセスを開始してクエリを実行します。 |
| px_workers | エラスティックパラレルクエリが特定のテーブルに適用されるかどうかを指定します。デフォルトでは適用されません。この機能はクラスターリソースを大量に消費するため、明示的に設定されたテーブルに対してのみ有効にすることを推奨します。例:
|
| synchronous_commit | トランザクションコミットがクライアントに成功メッセージを返す前に、WAL ログがディスクに書き込まれるのを待つ必要があるかどうかを指定します。有効な値は次のとおりです:
説明 PX モードでは、このパラメーターを on に設定する必要があります。 |
例
この例では、単純な単一テーブルクエリを使用して、エラスティックパラレルクエリの使用方法を示します。
背景情報:
次のコマンドを実行して test テーブルを作成し、サンプルデータを挿入します。
CREATE TABLE test(id int);
INSERT INTO test SELECT generate_series(1,1000000);
EXPLAIN SELECT * FROM test;
デフォルトでは、エラスティックパラレルクエリは無効になっています。クエリの実行計画には、ネイティブの Seq Scan が表示されます:
QUERY PLAN
--------------------------------------------------------
Seq Scan on test (cost=0.00..35.50 rows=2550 width=4)
(1 row)
次の手順に従って、エラスティックパラレルクエリを有効にして使用します:
testテーブルに対してエラスティックパラレルクエリを有効にします。ALTER TABLE test SET (px_workers=1); SET polar_enable_px=on; EXPLAIN SELECT * FROM test;結果は次のようになります:
QUERY PLAN ------------------------------------------------------------------------------- PX Coordinator 2:1 (slice1; segments: 2) (cost=0.00..431.00 rows=1 width=4) -> Seq Scan on test (scan partial) (cost=0.00..431.00 rows=1 width=4) Optimizer: PolarDB PX Optimizer (3 rows)- 現在のすべての読み取り専用ノードの名前をクエリします。
次のコマンドを実行します:
SHOW polar_cluster_map;結果は次のようになります:
polar_cluster_map ------------------- node1,node2,node3 (1 row)この結果は、クラスターに
node1、node2、node3の 3 つの読み取り専用ノードがあることを示しています。 node1とnode2の読み取り専用ノードのみがエラスティックパラレルクエリに参加するように指定します。次のコマンドを実行します:
SET polar_px_nodes='node1,node2';参加しているノードをクエリします:
SHOW polar_px_nodes ;結果は次のようになります:
polar_px_nodes ---------------- node1,node2 (1 row)
パフォーマンスデータ
以下のパフォーマンスデータは、5 つの読み取り専用ノードを持つテスト環境で記録されたものです:
- フルテーブルスキャン (
SELECT COUNT(*)) の場合、エラスティックパラレルクエリはシングルノードのパラレルクエリよりも 60 倍高速でした。 - TPC-H ワークロードの場合、エラスティックパラレルクエリはシングルノードのパラレルクエリよりも 30 倍高速でした。説明 この例では、TPC-H ベンチマークに基づくテストが実装されていますが、TPC-H ベンチマークテストのすべての要件を満たしているわけではありません。したがって、テスト結果は、公開されている TPC-H ベンチマークテストの結果とは比較できない場合があります。
詳細な制御の適用
このセクションでは、さまざまな粒度レベルでエラスティックパラレルクエリを使用する方法について説明します。
- システムレベルの制御
グローバル GUC パラメーターを設定して機能を有効にし、並列度 (DoP) を指定することで、システムレベルでエラスティックパラレルクエリを制御できます。
例postgres=# alter system set polar_enable_px=1; ALTER SYSTEM postgres=# alter system set polar_px_dop_per_node=1; ALTER SYSTEM postgres=# select pg_reload_conf(); pg_reload_conf ---------------- t (1 row) postgres=# \c postgres You are now connected to database "postgres" as user "postgres". postgres=# drop table if exists t1; DROP TABLE postgres=# select id into t1 from generate_series(1, 1000) as id order by id desc; SELECT 1000 postgres=# alter table t1 set (px_workers=1); ALTER TABLE postgres=# explain (verbose, costs off) select * from t1 where id < 10; QUERY PLAN ------------------------------------------- PX Coordinator 2:1 (slice1; segments: 2) Output: id -> Partial Seq Scan on public.t1 Output: id Filter: (t1.id < 10) Optimizer: PolarDB PX Optimizer (6 rows) - セッションレベルの制御
`ALTER SESSION` 構文を使用するか、セッションレベルの GUC パラメーターを設定することで、現在のセッションのエラスティックパラレルクエリを制御できます。
- ALTER SESSION 構文
ALTER SESSION ENABLE PARALLEL QUERY ALTER SESSION DISABLE PARALLEL QUERY ALTER SESSION FORCE PARALLEL QUERY [PARALLEL integer]説明ALTER SESSION ENABLE PARALLEL QUERYは、現在のセッションがヒントやパラレル構文を使用してパラレルクエリを有効にすることを許可します。ALTER SESSION DISABLE PARALLEL QUERYは、現在のセッションにシリアル実行を強制します。パラレルクエリは無効になり、すべてのパラレルヒントや構文は無視されます。ALTER SESSION FORCE PARALLEL QUERY [PARALLEL integer]は、現在のセッションにパラレル実行を強制します。オプションでPARALLEL integerを使用して並列度 (DoP) を指定できます。省略した場合、システムはpolar_px_dop_per_nodeパラメーターの DoP を使用します。最終的な DoP は、ヒント >
FORCE PARALLEL句 >polar_px_dop_per_nodeパラメーターの優先順位で決定されます。
このコマンドは現在のセッションにのみ影響し、再接続するとリセットされます。デフォルト値は
enableです。例--enable postgres=# set polar_enable_px = false; SET postgres=# set polar_px_enable_hint = true; SET postgres=# alter session enable parallel query; ALTER SESSION postgres=# explain (verbose, costs off) select /*+ PARALLEL(4)*/ * from t1 where id < 10; INFO: [HINTS] PX PARALLEL(4) accepted. QUERY PLAN ------------------------------------------- PX Coordinator 8:1 (slice1; segments: 8) Output: id -> Partial Seq Scan on public.t1 Output: id Filter: (t1.id < 10) Optimizer: PolarDB PX Optimizer (6 rows)--disable postgres=# set polar_enable_px = false; SET postgres=# set polar_px_enable_hint = true; SET postgres=# alter session disable parallel query; ALTER SESSION postgres=# explain (verbose, costs off) select /*+ PARALLEL(4)*/ * from t1 where id < 10; QUERY PLAN ------------------------ Seq Scan on public.t1 Output: id Filter: (t1.id < 10) (3 rows)--force postgres=# set polar_enable_px = false; SET postgres=# set polar_px_enable_hint = false; SET postgres=# alter session force parallel query; ALTER SESSION postgres=# explain (verbose, costs off) select * from t1 where id < 10; QUERY PLAN ------------------------------------------- PX Coordinator 2:1 (slice1; segments: 2) Output: id -> Partial Seq Scan on public.t1 Output: id Filter: (t1.id < 10) Optimizer: PolarDB PX Optimizer (6 rows) postgres=# alter session force parallel query parallel 2; ALTER SESSION postgres=# explain (verbose, costs off) select * from t1 where id < 10; QUERY PLAN ------------------------------------------- PX Coordinator 4:1 (slice1; segments: 4) Output: id -> Partial Seq Scan on public.t1 Output: id Filter: (t1.id < 10) Optimizer: PolarDB PX Optimizer (6 rows) - GUC パラメーター制御
GUC パラメーターはシステムレベルとセッションレベルの両方で設定できるため、特定のセッションの動作を制御するためにも使用できます。
例postgres=# set polar_enable_px = true; SET postgres=# set polar_px_dop_per_node = 1; SET postgres=# explain (verbose, costs off) select * from t1 where id < 10; QUERY PLAN ------------------------------------------- PX Coordinator 2:1 (slice1; segments: 2) Output: id -> Partial Seq Scan on public.t1 Output: id Filter: (t1.id < 10) Optimizer: PolarDB PX Optimizer (6 rows)
- ALTER SESSION 構文
- クエリレベルの制御
SQL ヒントを使用して、特定のクエリがエラスティックパラレルクエリを使用するかどうかを制御し、その並列度 (DoP) を設定できます。ヒントの構文は次のとおりです:
/*+ PARALLEL(DEFAULT) */ /*+ PARALLEL(integer) */ /*+ NO_PARALLEL(tablename) */説明PARALLEL(DEFAULT)は、クエリが polar_px_dop_per_node パラメーターで定義されたデフォルトの並列度でエラスティックパラレルクエリを使用することを指定します。PARALLEL(integer)は、クエリが指定された並列度でエラスティックパラレルクエリを使用することを指定します。NO_PARALLEL(tablename)は、指定されたテーブルがパラレルでクエリされるのを防ぎます。クエリにこのテーブルが含まれている場合、クエリ全体がシリアルで実行されます。- Oracle との互換性のため、パラレルヒントを混在させる場合は次のルールが適用されます:
- 複数のヒントブロック、例えば /*+ A */ /*+ B */ /*+ C */ の場合、最初のヒントブロックのみが有効になります。
- 単一のヒントブロックで複数のパラレルヒントが使用され、例えば /*+ parallel(A) parallel(B) */ のように DoP の値が異なる場合、ヒントは競合し、すべてのパラレルヒントは無視されます。値が同じ場合、ヒントは適用されます。
- 同じブロックで
parallelヒントとno_parallelヒントが使用された場合、例えば /*+ parallel(A) no_parallel(t1) */ のように、no_parallelヒントは無視されます。
- 現在、パラレルクエリでは
parallelとno_parallelヒントのみがサポートされています。 - クエリレベルの制御にヒントを使用するには、polar_px_enable_hint GUC パラメーターを true に設定する必要があります。デフォルトでは false です。
例postgres=# set polar_enable_px = false; SET postgres=# set polar_px_dop_per_node = 1; SET postgres=# set polar_px_enable_hint = true; SET postgres=# explain (verbose, costs off) select * from t1 where id < 10; QUERY PLAN ------------------------ Seq Scan on public.t1 Output: id Filter: (t1.id < 10) (3 rows) postgres=# explain (verbose, costs off) select /*+ PARALLEL(DEFAULT) */ * from t1 where id < 10; QUERY PLAN ------------------------------------------- PX Coordinator 2:1 (slice1; segments: 2) Output: id -> Partial Seq Scan on public.t1 Output: id Filter: (t1.id < 10) Optimizer: PolarDB PX Optimizer (6 rows) postgres=# explain (verbose, costs off) select /*+ PARALLEL(4) */ * from t1 where id < 10; QUERY PLAN ------------------------------------------- PX Coordinator 8:1 (slice1; segments: 8) Output: id -> Partial Seq Scan on public.t1 Output: id Filter: (t1.id < 10) Optimizer: PolarDB PX Optimizer (6 rows) postgres=# explain (verbose, costs off) select /*+ PARALLEL(0) */ * from t1 where id < 10; QUERY PLAN ------------------------ Seq Scan on public.t1 Output: id Filter: (t1.id < 10) (3 rows) postgres=# explain (verbose, costs off) select /*+ NO_PARALLEL(t1) */ * from t1 where id < 10; QUERY PLAN ------------------------ Seq Scan on public.t1 Output: id Filter: (t1.id < 10) (3 rows) - 異なるレベルの組み合わせ効果
異なるレベルの設定が組み合わされた場合、最終的な動作は次のルールによって決定されます:
システムレベル セッションレベル クエリレベル 結果 polar_enable_px=on polar_px_dop_per_node=X enable ヒントなし パラレル、DoP X polar_enable_px=on polar_px_dop_per_node=X enable PARALLEL(Y) パラレル、DoP Y polar_enable_px=on polar_px_dop_per_node=X enable NO_PARALLEL シリアル polar_enable_px=on polar_px_dop_per_node=X disable ヒントなし シリアル polar_enable_px=on polar_px_dop_per_node=X disable PARALLEL(Y) シリアル polar_enable_px=on polar_px_dop_per_node=X disable NO_PARALLEL シリアル polar_enable_px=on polar_px_dop_per_node=X FORCE PARALLEL Z ヒントなし パラレル、DoP Z polar_enable_px=on polar_px_dop_per_node=X FORCE PARALLEL Z PARALLEL(Y) パラレル、DoP Y polar_enable_px=on polar_px_dop_per_node=X FORCE PARALLEL Z NO_PARALLEL シリアル polar_enable_px=off polar_px_dop_per_node=X enable ヒントなし シリアル polar_enable_px=off polar_px_dop_per_node=X enable PARALLEL(Y) パラレル、DoP Y polar_enable_px=off polar_px_dop_per_node=X enable NO_PARALLEL シリアル polar_enable_px=off polar_px_dop_per_node=X disable ヒントなし シリアル polar_enable_px=off polar_px_dop_per_node=X disable PARALLEL(Y) シリアル polar_enable_px=off polar_px_dop_per_node=X disable NO_PARALLEL シリアル polar_enable_px=off polar_px_dop_per_node=X FORCE PARALLEL Z ヒントなし パラレル、DoP Z polar_enable_px=off polar_px_dop_per_node=X FORCE PARALLEL Z PARALLEL(Y) パラレル、DoP Y polar_enable_px=off polar_px_dop_per_node=X FORCE PARALLEL Z NO_PARALLEL シリアル