パラレル度(Degree Of Parallelism、略称DOP)とは、単一のDFO(Data Flow Operator)が実行時に使用するワーカースレッド数を指します。
パラレル実行の設計目的は、マルチコアリソースを効率的に活用することです。OceanBaseのパラレル実行フレームワークでは、パラレル度を指定するためのさまざまな方法が提供されており、手動で指定することも、データベースによる自動選択を許可することも可能です。
パラレル度の推奨値
単純な原則として、PARALLELの設定はCPUリソースを最大限に活用することを目的としており、単に最大値を追求するわけではありません。
例
テナントのCPU数が20であると仮定します:
- 単一テーブルに対する単純な操作(単一テーブルのスキャンフィルタリング、単一テーブルの追加・削除・更新など)では、PARALLELの理論値を20に設定できます。
- 複数テーブルの
JOINクエリやグローバルインデックスを持つPDMLでは、PARALLELの理論値を10に設定できます。 - より複雑な計画で、右側の深い木構造(つまり、実行計画内の操作ツリーの右側のより深い部分)の場合、PARALLELの理論値を約7に設定できます。
例の説明
現在のテナントのCPU数が20の場合:
単一テーブル操作では、DFOは1つしかないため、全20個のCPUをそのDFOに割り当てることができます。
例えば、そのDFOが大部分の時間をI/O操作に費やしている場合、CPUを最大限に活用するために、パラレル度を25などやや高く設定できます。
フィンチュアリング後、単一テーブルの単純な操作(単一テーブルのスキャンフィルタリング、単一テーブルの追加・削除・更新など)におけるPARALLELの実際の値は30になります。
複数テーブルの
JOINでは、同時に2つのDFOが起動し、データパイプラインを形成します(1つのDFOがプロデューサー、もう1つがコンシューマー)。したがって、各DFOに10個のCPUを割り当てることができます。実際には、各DFOが割り当てられたCPUを最大限に活用できるとは限りません。そのため、CPUをより十分に活用するために、例えば15に設定するなど、適切にパラレル度を調整できます。ただし、無限にパラレル度を増やすべきではありません。50に設定しても実質的なメリットはなく、むしろスレッドスケジューリングオーバーヘッドとフレームワークスケジューリングオーバーヘッドが増加します。
フィンチュアリング後、複数テーブルの
JOINクエリやグローバルインデックスを持つPDMLにおけるPARALLELの実際の値は15になります。右側の深い木構造の計画について、簡単なSQLクエリを例に挙げて説明します。
SELECT /*+ parallel(10) */ column1, column2 FROM table1 WHERE condition1;このクエリでは、
parallel(10)ヒントを使用して、システムにパラレル度10の計画で実行するよう求めています。実行計画は以下のように仮定します:====================================================================== | ID | OPERATOR | NAME | EST.ROWS | EST.TIME(us)| ---------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | | 1 | PX COORDINATOR | | | | | 2 | PX SEND QC (RANDOM) | :EX10000| | | | 3 | PX BLOCK ITERATOR | | N rows | | | 4 | TABLE ACCESS (FULL) | table1 | N rows | | ======================================================================この実行計画では、右側の深い木構造の部分が操作ツリーの右側にあることがわかります。例えば、操作記号が
PX SEND QCやPX BLOCK ITERATORの部分です。この段階では、複数のDFOが起動され、各DFOが計画の一部を実行します。システムがこの右側の深い木構造の計画の特定の部分で同時に3つのDFOを起動し、各DFOに7個のCPUを割り当てることを決定したとします。これは、各DFOが計算リソースを最大限に活用し、全体のクエリ性能を向上させることを目的としています。
フィンチュアリング後、パラレル度を10~15に設定することで、異なる部分の計画に必要とされる可能性のあるパラレル度に適応するため、システムにより大きなパラレル実行スペースを提供します。このような調整は、大規模なデータセットを処理する場合や、高いパラレル度での実行が必要なクエリの場合に、全体的な性能を向上させることができます。
パラレル度を手動で指定する
テーブルのパラレル度を手動で指定することで、そのテーブルをスキャンする際に常にパラレル実行が使用されるように保証できます。OceanBaseでは、OracleモードとMySQLモードの構文が若干異なります。
MySQLモードで手動で並列度を指定する
テーブル属性による並列度の指定
以下のステートメントは、それぞれメインテーブルとインデックスのスキャン並列度を指定しています。
ALTER TABLE table_name PARALLEL 4;
ALTER TABLE table_name ALTER INDEX index_name PARALLEL 2;
SQL文が1つのテーブルのみを対象とする場合、メインテーブルが照会されている場合は、メインテーブルが存在するDFOに加えて、他のDFOも並列度4で実行されます。インデックステーブルが照会されている場合は、インデックステーブルが存在するDFOに加えて、他のDFOも並列度2で実行されます。
SQL文が複数のテーブルを対象とする場合は、PARALLELの最大値がプラン全体のDOPとして使用されます。
PARALLEL HINTによる並列度の指定
グローバルなPARALLEL HINTを使用して、SQL全体の並列度を指定することができます。また、テーブルレベルのPARALLEL HINTを使用して、特定のテーブルの並列度を指定することもできます。1つのSQL文内で複数のテーブルに対してPARALLEL HINTが指定されている場合、各テーブルが属するDFOのDOPは、それぞれのテーブルのParallel値によって決定されます。1つのDFO内に複数のテーブルが含まれている場合、その中で最大のPARALLEL値がそのDFOのDOPとなります。
グローバルHINT:
obclient> CREATE TABLE t1 (c1 INT, c2 INT);
Query OK, 0 rows affected
obclient> EXPLAIN SELECT /*+ parallel(3) */ SUM(c1) FROM t1;
+---------------------------------------------------------------------+
| Query Plan |
+---------------------------------------------------------------------+
| ============================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ------------------------------------------------------------- |
| |0 |SCALAR GROUP BY | |1 |3 | |
| |1 |└─PX COORDINATOR | |3 |3 | |
| |2 | └─EXCHANGE OUT DISTR |:EX10000|3 |2 | |
| |3 | └─MERGE GROUP BY | |3 |2 | |
| |4 | └─PX BLOCK ITERATOR| |1 |2 | |
| |5 | └─TABLE FULL SCAN|t1 |1 |2 | |
| ============================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([T_FUN_SUM(T_FUN_SUM(t1.c1))]), filter(nil), rowset=16 |
| group(nil), agg_func([T_FUN_SUM(T_FUN_SUM(t1.c1))]) |
| 1 - output([T_FUN_SUM(t1.c1)]), filter(nil), rowset=16 |
| 2 - output([T_FUN_SUM(t1.c1)]), filter(nil), rowset=16 |
| dop=3 |
| 3 - output([T_FUN_SUM(t1.c1)]), filter(nil), rowset=16 |
| group(nil), agg_func([T_FUN_SUM(t1.c1)]) |
| 4 - output([t1.c1]), filter(nil), rowset=16 |
| 5 - output([t1.c1]), filter(nil), rowset=16 |
| access([t1.c1]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([t1.__pk_increment]), range(MIN ; MAX)always true |
+---------------------------------------------------------------------+
24 rows in set
テーブルレベルHINT:
obclient> CREATE TABLE t1 (c1 INT, c2 INT);
Query OK, 0 rows affected
obclient> CREATE TABLE t2 (c1 INT, c2 INT);
Query OK, 0 rows affected
obclient> EXPLAIN SELECT /*+ parallel(t1 3)+ parallel(t2 2)*/ * FROM t1, t2 WHERE t1.c1 = t2.c1;
obclient [t]> EXPLAIN SELECT /*+ parallel(t1 3)+ parallel(t2 2)*/ * FROM t1, t2 WHERE t1.c1 = t2.c1;
+---------------------------------------------------------------------------------------+
| Query Plan |
+---------------------------------------------------------------------------------------+
| ======================================================================== |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ------------------------------------------------------------------------ |
| |0 |PX COORDINATOR | |1 |6 | |
| |1 |└─EXCHANGE OUT DISTR |:EX10001|1 |5 | |
| |2 | └─SHARED HASH JOIN | |1 |4 | |
| |3 | ├─EXCHANGE IN DISTR | |1 |2 | |
| |4 | │ └─EXCHANGE OUT DISTR (BC2HOST)|:EX10000|1 |2 | |
| |5 | │ └─PX BLOCK ITERATOR | |1 |2 | |
| |6 | │ └─TABLE FULL SCAN |t1 |1 |2 | |
| |7 | └─PX BLOCK ITERATOR | |1 |2 | |
| |8 | └─TABLE FULL SCAN |t2 |1 |2 | |
| ======================================================================== |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t2.c1, t2.c2)]), filter(nil), rowset=16 |
| 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t2.c1, t2.c2)]), filter(nil), rowset=16 |
| dop=2 |
| 2 - output([t1.c1], [t2.c1], [t1.c2], [t2.c2]), filter(nil), rowset=16 |
| equal_conds([t1.c1 = t2.c1]), other_conds(nil) |
| 3 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 |
| 4 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 |
| dop=3 |
| 5 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 |
| 6 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 |
| access([t1.c1], [t1.c2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([t1.__pk_increment]), range(MIN ; MAX)always true |
| 7 - output([t2.c1], [t2.c2]), filter(nil), rowset=16 |
| 8 - output([t2.c1], [t2.c2]), filter(nil), rowset=16 |
| access([t2.c1], [t2.c2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([t2.__pk_increment]), range(MIN ; MAX)always true |
+---------------------------------------------------------------------------------------+
33 rows in set
SESSION上で並列度を指定する
現在のセッションで並列度が一度指定されると、そのセッション内のすべてのクエリステートメントは指定された並列度で実行されます。単一行のクエリであっても、この並列度が適用されるため、パフォーマンスが低下する可能性があることにご注意ください。
set _force_parallel_query_dop = 3;
DMLステートメントについては、上記のコマンドを使用しても、クエリ部分のみがパラレル実行され、書き込み部分は依然として直列です。書き込み部分も並列化したい場合は、次のコマンドを使用する必要があります:
set _force_parallel_dml_dop = 3;
_force_parallel_query_dop を1より大きな値に変更すると、現在のセッション上のクエリはすべて1より大きな並列度で実行されます。_force_parallel_query_dop を1に変更すると、現在のセッション上のSQLではパラレル実行が有効になりません。
注意が必要な点として、ここでの設定はDMLステートメントを含むセッション全体のクエリに対してグローバルに適用されるということです。そのため、これらの設定を使用する際には、セッション全体の実行への影響を十分に理解し、慎重に行う必要があります。
Oracleモードでの並列度の手動指定
テーブル属性で並列度を指定する
以下のステートメントは、それぞれ1つのプライマリテーブルと1つのインデックスのスキャン並列度を指定します。
ALTER TABLE table_name PARALLEL 4;
ALTER INDEX index_name PARALLEL 2;
SQL文に1つのテーブルしか含まれていない場合、そのSQL文がプライマリテーブルを照会するとき、プライマリテーブルが存在するDFOに加えて、他のDFOも並列度4で実行されます。また、SQL文がインデックステーブルを照会するとき、インデックステーブルが存在するDFOに加えて、他のDFOも並列度2で実行されます。
SQL文に複数のテーブルが含まれる場合、PARALLELの最大値がプラン全体のDOPとして使用されます。
PARALLEL HINTによる並列度の指定
グローバルなPARALLEL HINTを使用して、SQL全体の並列度を指定することができます。また、テーブルレベルのPARALLEL HINTを使用して、特定のテーブルの並列度を指定することもできます。
あるSQL文内で複数のテーブルにPARALLEL HINTが指定されている場合、各テーブルが属するDFOのDOPは、それぞれのテーブルのPARALLEL値によって決定されます。1つのDFO内に複数のテーブルが含まれている場合は、それらのPARALLEL値のうち最大値がそのDFOのDOPとなります。
グローバルHINT:
obclient> CREATE TABLE t1 (c1 INT, c2 INT);
Query OK, 0 rows affected
obclient> EXPLAIN SELECT /*+ parallel(3) */ SUM(c1) FROM t1;
+----------------------------------------------------------------------+
| Query Plan |
+----------------------------------------------------------------------+
| ========================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| --------------------------------------------------------- |
| |0 |SCALAR GROUP BY | |1 |2 | |
| |1 | PX COORDINATOR | |3 |2 | |
| |2 | EXCHANGE OUT DISTR |:EX10000|3 |2 | |
| |3 | MERGE GROUP BY | |3 |1 | |
| |4 | PX BLOCK ITERATOR| |1 |1 | |
| |5 | TABLE SCAN |T1 |1 |1 | |
| ========================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([T_FUN_SUM(T_FUN_SUM(T1.C1))]), filter(nil), rowset=256 |
| group(nil), agg_func([T_FUN_SUM(T_FUN_SUM(T1.C1))]) |
| 1 - output([T_FUN_SUM(T1.C1)]), filter(nil), rowset=256 |
| 2 - output([T_FUN_SUM(T1.C1)]), filter(nil), rowset=256 |
| dop=3 |
| 3 - output([T_FUN_SUM(T1.C1)]), filter(nil), rowset=256 |
| group(nil), agg_func([T_FUN_SUM(T1.C1)]) |
| 4 - output([T1.C1]), filter(nil), rowset=256 |
| 5 - output([T1.C1]), filter(nil), rowset=256 |
| access([T1.C1]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
+----------------------------------------------------------------------+
24 rows in set
テーブルレベルHINT:
obclient> CREATE TABLE t1 (c1 INT, c2 INT);
Query OK, 0 rows affected
obclient> CREATE TABLE t2 (c1 INT, c2 INT);
Query OK, 0 rows affected
obclient> SELECT /*+ parallel(t1 3) */ * FROM t1, t2 WHERE t1.c2 = t2.c1;
Empty set
obclient> EXPLAIN SELECT /*+ parallel(t1 3) */ * FROM t1, t2 WHERE t1.c2 = t2.c1;
+----------------------------------------------------------------------------------------+
| Query Plan |
+----------------------------------------------------------------------------------------+
| ================================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ----------------------------------------------------------------- |
| |0 |PX COORDINATOR | |1 |2 | |
| |1 | EXCHANGE OUT DISTR |:EX10002|1 |6 | |
| |2 | HASH JOIN | |1 |5 | |
| |3 | EXCHANGE IN DISTR | |1 |2 | |
| |4 | EXCHANGE OUT DISTR (HASH)|:EX10000|1 |2 | |
| |5 | PX BLOCK ITERATOR | |1 |1 | |
| |6 | TABLE SCAN |T1 |1 |1 | |
| |7 | EXCHANGE IN DISTR | |1 |4 | |
| |8 | EXCHANGE OUT DISTR (HASH)|:EX10001|1 |4 | |
| |9 | PX PARTITION ITERATOR | |1 |2 | |
| |10| TABLE SCAN |T2 |1 |2 | |
| ================================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([INTERNAL_FUNCTION(T1.C1, T1.C2, T2.C1, T2.C2)]), filter(nil), rowset=256 |
| 1 - output([INTERNAL_FUNCTION(T1.C1, T1.C2, T2.C1, T2.C2)]), filter(nil), rowset=256 |
| dop=3 |
| 2 - output([T1.C2], [T2.C1], [T1.C1], [T2.C2]), filter(nil), rowset=256 |
| equal_conds([T1.C2 = T2.C1]), other_conds(nil) |
| 3 - output([T1.C2], [T1.C1]), filter(nil), rowset=256 |
| 4 - output([T1.C2], [T1.C1]), filter(nil), rowset=256 |
| (#keys=1, [T1.C2]), dop=3 |
| 5 - output([T1.C2], [T1.C1]), filter(nil), rowset=256 |
| 6 - output([T1.C2], [T1.C1]), filter(nil), rowset=256 |
| access([T1.C2], [T1.C1]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T1.__pk_increment]), range(MIN ; MAX)always true |
| 7 - output([T2.C1], [T2.C2]), filter(nil), rowset=256 |
| 8 - output([T2.C1], [T2.C2]), filter(nil), rowset=256 |
| (#keys=1, [T2.C1]), dop=1 |
| 9 - output([T2.C1], [T2.C2]), filter(nil), rowset=256 |
| force partition granule |
| 10 - output([T2.C1], [T2.C2]), filter(nil), rowset=256 |
| access([T2.C1], [T2.C2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T2.__pk_increment]), range(MIN ; MAX)always true |
+----------------------------------------------------------------------------------------+
39 rows in set
DMLステートメントについては、上記のHINTを使用しても、クエリ部分のみがパラレル実行され、書き込み部分は引き続きシリアルです。書き込み部分も並列化したい場合は、HINT ENABLE_PARALLEL_DMLを追加する必要があります。例えば:
INSERT /*+ parallel(3) enable_parallel_dml */ INTO t3 SELECT * FROM t1;
注意
DMLの並列処理を有効にするには、グローバルなparallel hintを指定する必要があります。テーブルレベルのparallel hintのみを指定しても、書き込み部分をシリアルにすることはできません。たとえば、以下のSQLではDMLの並列処理は有効になりません:INSERT /*+ parallel(t3 3) enable_parallel_dml */ INTO t3 SELECT * FROM t1;
SESSION上で並列度を指定する
現在のセッションで並列度が指定されると、そのセッション内のすべてのクエリステートメントは指定された並列度で実行されます。単一行のクエリであっても、この並列度が適用されるため、パフォーマンスが低下する可能性があることにご注意ください。
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 3;
DMLステートメントについては、上記のコマンドを使用しても、クエリ部分のみがパラレル実行され、書き込み部分は依然として直列です。書き込み部分も並列化したい場合は、次のコマンドを使用します:
ALTER SESSION FORCE PARALLEL DML PARALLEL 3;
セッションレベルの並列処理を無効にするには、次のコマンドを使用します:
ALTER SESSION DISABLE PARALLEL QUERY;
自動並列度
自動並列度の詳細については、Auto DOPを参照してください。
パラレル度の優先順位
TABLE HINT > グローバルHINT > SESSIONパラレル度 > TABLE DOP
グローバルHINTとTABLE HINTの優先順位を比較します。テーブルHINTがある場合、グローバルHINTは無効になります。
obclient> CREATE TABLE t1 (c1 int primary key, c2 int);
obclient> EXPLAIN SELECT /*+ parallel(3) parallel(t1 5) */ * FROM t1;
+-------------------------------------------------------------------------+
| Query Plan |
+-------------------------------------------------------------------------+
| ======================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ------------------------------------------------------- |
| |0 |PX COORDINATOR | |1 |1 | |
| |1 | EXCHANGE OUT DISTR|:EX10000|1 |21 | |
| |2 | PX BLOCK ITERATOR| |1 |1 | |
| |3 | TABLE SCAN |T1 |1 |1 | |
| ======================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c2)]), filter(nil), rowset=16 |
| 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c2)]), filter(nil), rowset=16 |
| dop=5 |
| 2 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 |
| 3 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 |
| access([t1.c1], [t1.c2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([t1.c1]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------------+
18 rows in set
obclient> EXPLAIN SELECT /*+ parallel(t1 3) */ * FROM t1;
+-------------------------------------------------------------------------+
| Query Plan |
+-------------------------------------------------------------------------+
| ======================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| ------------------------------------------------------- |
| |0 |PX COORDINATOR | |1 |2 | |
| |1 | EXCHANGE OUT DISTR|:EX10000|1 |1 | |
| |2 | PX BLOCK ITERATOR| |1 |1 | |
| |3 | TABLE SCAN |T1 |1 |1 | |
| ======================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c2)]), filter(nil), rowset=16 |
| 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c2)]), filter(nil), rowset=16 |
| dop=3 |
| 2 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 |
| 3 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 |
| access([t1.c1], [t1.c2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([t1.c1]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------------+
18 rows in set
SESSIONとTABLE HINTの優先順位を比較します。テーブルレベルのHINTを使用する場合、SESSIONで設定されたDOPは無効になります。
obclient> ALTER SESSION FORCE PARALLEL QUERY PARALLEL 4;
Query OK, 0 rows affected (0.001 sec)
obclient> EXPLAIN SELECT /*+ parallel(t1 3) */ * FROM t1;
+-------------------------------------------------------------------------+
| Query Plan |
+-------------------------------------------------------------------------+
| ========================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| --------------------------------------------------------- |
| |0 |PX COORDINATOR | |1 |3 | |
| |1 |└─EXCHANGE OUT DISTR |:EX10000|1 |2 | |
| |2 | └─PX BLOCK ITERATOR| |1 |2 | |
| |3 | └─TABLE FULL SCAN|T1 |1 |2 | |
| ========================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([INTERNAL_FUNCTION(T1.C1, T1.C2)]), filter(nil), rowset=16 |
| 1 - output([INTERNAL_FUNCTION(T1.C1, T1.C2)]), filter(nil), rowset=16 |
| dop=3 |
| 2 - output([T1.C1], [T1.C2]), filter(nil), rowset=16 |
| 3 - output([T1.C1], [T1.C2]), filter(nil), rowset=16 |
| access([T1.C1], [T1.C2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T1.C1]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------------+
18 rows in set
obclient> EXPLAIN SELECT * FROM t1;
+-------------------------------------------------------------------------+
| Query Plan |
+-------------------------------------------------------------------------+
| ========================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| --------------------------------------------------------- |
| |0 |PX COORDINATOR | |1 |2 | |
| |1 |└─EXCHANGE OUT DISTR |:EX10000|1 |2 | |
| |2 | └─PX BLOCK ITERATOR| |1 |1 | |
| |3 | └─TABLE FULL SCAN|T1 |1 |1 | |
| ========================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([INTERNAL_FUNCTION(T1.C1, T1.C2)]), filter(nil), rowset=16 |
| 1 - output([INTERNAL_FUNCTION(T1.C1, T1.C2)]), filter(nil), rowset=16 |
| dop=4 |
| 2 - output([T1.C1], [T1.C2]), filter(nil), rowset=16 |
| 3 - output([T1.C1], [T1.C2]), filter(nil), rowset=16 |
| access([T1.C1], [T1.C2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T1.C1]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------------+
18 rows in set
SESSIONとTABLE PARALLELの優先順位を比較します。テーブルPARALLELプロパティの優先順位は、SESSIONで指定されたDOPの優先順位よりも低いことがわかります。
obclient> ALTER TABLE t1 PARALLEL 5;
Query OK, 0 rows affected
obclient> EXPLAIN SELECT * FROM t1;
+-------------------------------------------------------------------------+
| Query Plan |
+-------------------------------------------------------------------------+
| ========================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| --------------------------------------------------------- |
| |0 |PX COORDINATOR | |1 |2 | |
| |1 |└─EXCHANGE OUT DISTR |:EX10000|1 |2 | |
| |2 | └─PX BLOCK ITERATOR| |1 |1 | |
| |3 | └─TABLE FULL SCAN|T1 |1 |1 | |
| ========================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([INTERNAL_FUNCTION(T1.C1, T1.C2)]), filter(nil), rowset=16 |
| 1 - output([INTERNAL_FUNCTION(T1.C1, T1.C2)]), filter(nil), rowset=16 |
| dop=4 |
| 2 - output([T1.C1], [T1.C2]), filter(nil), rowset=16 |
| 3 - output([T1.C1], [T1.C2]), filter(nil), rowset=16 |
| access([T1.C1], [T1.C2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T1.C1]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------------+
18 rows in set
obclient> ALTER SESSION FORCE PARALLEL QUERY PARALLEL 4;
Query OK, 0 rows affected
obclient> EXPLAIN SELECT * FROM t1;
+-------------------------------------------------------------------------+
| Query Plan |
+-------------------------------------------------------------------------+
| ========================================================= |
| |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| |
| --------------------------------------------------------- |
| |0 |PX COORDINATOR | |1 |2 | |
| |1 |└─EXCHANGE OUT DISTR |:EX10000|1 |2 | |
| |2 | └─PX BLOCK ITERATOR| |1 |1 | |
| |3 | └─TABLE FULL SCAN|T1 |1 |1 | |
| ========================================================= |
| Outputs & filters: |
| ------------------------------------- |
| 0 - output([INTERNAL_FUNCTION(T1.C1, T1.C2)]), filter(nil), rowset=16 |
| 1 - output([INTERNAL_FUNCTION(T1.C1, T1.C2)]), filter(nil), rowset=16 |
| dop=4 |
| 2 - output([T1.C1], [T1.C2]), filter(nil), rowset=16 |
| 3 - output([T1.C1], [T1.C2]), filter(nil), rowset=16 |
| access([T1.C1], [T1.C2]), partitions(p0) |
| is_index_back=false, is_global_index=false, |
| range_key([T1.C1]), range(MIN ; MAX)always true |
+-------------------------------------------------------------------------+
18 rows in set