並列度(Degree Of Parallelism、DOPと略)とは、単一のDFO(Data Flow Operation)が実行時に使用するワーカースレッド数を指します。
パラレル実行の設計目的は、マルチコアリソースを効率的に活用することです。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がproducer、もう1つがconsumer)。したがって、各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が単一のテーブルのみに関連する場合、SQLがメインテーブルをクエリすると、メインテーブルが存在するDFO以外のDFOも並列度4で実行されます。SQLがインデックステーブルをクエリすると、インデックステーブルが存在するDFO以外のDFOも並列度2で実行されます。
SQLが複数のテーブルに関連する場合、PARALLELの最大値がプラン全体のDOPとして使用されます。
PARALLELヒントによる並列度の指定
グローバルPARALLELヒントを使用して、SQL全体の並列度を指定することも、テーブルレベルのPARALLELヒントを使用して、特定のテーブルの並列度を指定することもできます。SQL内で複数のテーブルにPARALLELヒントが指定されている場合、各テーブルが存在するDFOのDOPは、各テーブルのParallel値によって決定されます。DFO内に複数のテーブルが含まれる場合、それらのPARALLELの最大値がDFOのDOPとして使用されます。
グローバルヒント:
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
テーブルレベルヒント:
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上での並列度の指定
現在のsessionで並列度が指定されると、そのsession内のすべてのクエリステートメントは指定された並列度で実行されます。単一行クエリのSQLであっても、この並列度が使用されるため、パフォーマンスが低下する可能性があることに注意してください。
set _force_parallel_query_dop = 3;
DMLステートメントに上記のコマンドを使用しても、DMLステートメントのクエリ部分のみが並列実行され、書き込み部分は引き続き直列です。書き込み部分も並列にしたい場合は、以下のコマンドを使用する必要があります:
set _force_parallel_dml_dop = 3;
_force_parallel_query_dopが1より大きく変更されると、現在のsession上のクエリはすべて1より大きい並列度で実行されます。_force_parallel_query_dopが1に変更されると、現在のsession上のSQLは並列実行が有効になりません。
注意点として、ここでの設定は、DMLステートメントを含む、そのsession内のすべてのクエリに対してグローバルに適用されます。これらの設定を使用する際は、必ず慎重に行い、session全体の実行に与える影響を十分に理解しておく必要があります。
Oracleモードでの並列度の手動指定
テーブル属性による並列度の指定
以下のステートメントは、それぞれメインテーブルとインデックスのスキャン並列度を指定します。
ALTER TABLE table_name PARALLEL 4;
ALTER INDEX index_name PARALLEL 2;
あるSQLが単一のテーブルのみに関わる場合、そのSQLで主テーブルがクエリされたときは、主テーブルが存在するDFO以外の他のDFOも並列度4で実行されます。一方、SQLでインデックステーブルがクエリされたときは、インデックステーブルが存在するDFO以外の他のDFOも並列度2で実行されます。
1つのSQL文で複数のテーブルが関わる場合、そのパラレルの最大値がプラン全体のDOPとして設定されます。
PARALLEL HINTによる並列度の指定
グローバルPARALLEL HINTを使用すると、SQL全体の並列度を指定できます。また、テーブルレベルのPARALLEL HINTを使用して、特定のテーブルの並列度を指定することもできます。1つのSQLで両方のHINTが指定されている場合は
複数のテーブルに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を使用しても、DMLステートメントのクエリ部分のみが並列実行され、書き込み部分は引き続き直列です。書き込み部分も並列にしたい場合は、HINT ENABLE_PARALLEL_DMLを追加する必要があります。例:
INSERT /*+ parallel(3) enable_parallel_dml */ INTO t3 SELECT * FROM t1;
注意
並列DMLを使用する場合は、グローバルなparallelヒントを指定する必要があります。テーブルレベルのparallelヒントのみを指定しても、書き込み処理を部分的に直列化することはできません。例えば、以下のSQLではDMLの並列処理は有効になりません:INSERT /*+ parallel(t3 3) enable_parallel_dml */ INTO t3 SELECT * FROM t1;
SESSIONで並列度を指定する
現在のセッションで並列度が指定されると、そのセッション内のすべてのクエリステートメントは指定された並列度で実行されます。単一行を照会するSQLであってもこの並列度が適用されるため、パフォーマンスが低下する可能性があることに注意してください。
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 3;
DMLステートメントに対して上記のコマンドを使用すると、DMLステートメントのクエリ部分のみが並列実行され、書き込み部分は引き続き直列実行されます。書き込み部分も並列にしたい場合は、以下のコマンドを使用する必要があります:
ALTER SESSION FORCE PARALLEL DML PARALLEL 3;
セッションレベルの並列処理を無効にするには、以下のコマンドを使用します:
ALTER SESSION DISABLE PARALLEL QUERY;
自動並列度
自動並列度の詳細については、Auto DOPを参照してください。
パラレル度優先順位
TABLE HINT > グローバルHINT > SESSION並列度 > TABLE DOP
グローバルHINTとTABLE HINTの優先順位を比較します。TABLE 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 HINTとTABLE HINTの優先順位を比較します。TABLEレベルの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 HINTとTABLE PARALLELの優先順位を比較します。TABLE 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