The degree of parallelism (DOP), which is also known as the parallel degree, is the number of worker threads used by a distributed function operator (DFO) during execution.
The design of parallel execution aims to efficiently utilize multi-core resources. The OceanBase Database parallel execution framework allows you to specify the DOP in multiple ways, either manually or automatically by the database.
Recommended values
A simple principle is: the PARALLEL parameter is set to a value that makes full use of the CPU resources, rather than being set to the maximum value.
Examples
Assume that the tenant has 20 CPU cores. In this case:
- For simple operations on a single table (such as table scans, filtering, and DML operations), the theoretical value of PARALLEL can be set to 20.
- For
JOINqueries on multiple tables and global index-based PDML, the theoretical value of PARALLEL can be set to 10. - For complex plans in the form of right-deep trees (where the right side of the execution plan tree is deeper), the theoretical value of PARALLEL can be set to 7.
Examples explained
Assume that the tenant has 20 CPU cores in the following examples:
For single-table operations, only one DFO is generated. Therefore, all 20 CPU cores can be allocated to the DFO.
For example, if the DFO performs I/O operations for most of the time, a higher value, such as 25, can be set for the PARALLEL parameter to make full use of the CPU cores.
After fine tuning, the actual value of PARALLEL for simple operations on a single table (such as table scans and filtering) can be 30.
For
JOINqueries on multiple tables, two DFOs are generated to form a data processing pipeline (one DFO acts as the producer and the other as the consumer). Therefore, 10 CPU cores can be allocated to each DFO.In practice, each DFO cannot make full use of the allocated CPU cores. Therefore, the PARALLEL parameter can be adjusted, for example, to 15, to make better use of the CPU cores. However, the PARALLEL parameter should not be increased without limit. A value of 50 does not significantly improve performance but increases thread scheduling overheads and framework scheduling overheads.
After fine tuning, the actual value of PARALLEL for
JOINqueries on multiple tables and global index-based PDML can be 15.For right-deep tree plans, consider the following simple SQL query as an example:
SELECT /*+ parallel(10) */ column1, column2 FROM table1 WHERE condition1;In this query, the
parallel(10)hint is used to specify that a plan with a PARALLEL value of 10 be executed. Assume that the execution plan is as follows:====================================================================== | 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 | | ======================================================================In this execution plan, the right-deep tree plan is on the right side of the operator tree, for example, the
PX SEND QCandPX BLOCK ITERATORoperators. Multiple DFOs may be started in this stage, with each DFO responsible for executing a part of the plan.Assume that three DFOs are started in a right-deep tree plan at the same time, and each DFO is allocated seven CPU cores. This is done to ensure that each DFO can make full use of the computing resources and improve the overall query performance.
After fine tuning, the actual value of PARALLEL can be set to 10 to 15 to adapt to different parallel execution plans that may be required in different parts of the plan. This adjustment can enhance overall performance when processing large datasets or executing queries that require high parallelism.
Manually set the DOP
You can manually set the DOP of a table to ensure parallel execution when the table is scanned. The syntax is slightly different between the Oracle mode and MySQL mode of OceanBase Database.
Manually set the degree of parallelism in MySQL mode
Specify the DOP by using the table attribute
The following statements specify the DOP for a primary table and an index, respectively.
ALTER TABLE table_name PARALLEL 4;
ALTER TABLE table_name ALTER INDEX index_name PARALLEL 2;
If an SQL statement involves only one table, the DOP for querying the table is 4 in the DFO where the table is located, and 2 in other DFOs; if the SQL statement queries an index table, the DOP for querying the table is 2 in the DFO where the table is located, and 4 in other DFOs.
If an SQL statement involves multiple tables, the maximum value of the DOP specified for the tables is used as the DOP for the entire execution plan.
Specify the DOP by using the PARALLEL hint
You can use the global PARALLEL hint to specify the DOP for an entire SQL query, and you can use the table-level PARALLEL hint to specify the DOP for a specific table. If multiple tables are specified with the PARALLEL hint in one SQL query, the DOP for each DFO is determined by the DOPs of the tables. If multiple tables are included in one DFO, the maximum DOP of the tables is used as the DOP for the DFO.
Global 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
Table-level 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
Set the DOP for a session
Once the DOP is set for a session, the DOP for all statements in the session will be the specified DOP. Note that even single-row queries will be executed with the specified DOP, which may lead to performance degradation.
set _force_parallel_query_dop = 3;
For DML statements, the preceding command only enables parallel execution for the query part of the DML statement, while the write part remains sequential. To enable parallel execution for the write part as well, use the following command:
set _force_parallel_dml_dop = 3;
If you set _force_parallel_query_dop to a value greater than 1, all queries in the current session will be executed with a DOP greater than 1. If you set _force_parallel_query_dop to 1, parallel execution will be disabled for SQL statements in the session.
Keep in mind that the settings at the session level are global to all statements in the session, including DML statements. Therefore, when you use these settings, proceed with caution and make sure you understand the impact on the execution of the session.
Manually specify the DOP in Oracle mode
Specify the DOP for a table and an index
The following statements specify the DOP for a primary table and an index, respectively.
ALTER TABLE table_name PARALLEL 4;
ALTER INDEX index_name PARALLEL 2;
If an SQL statement involves only one table, when the statement queries the primary table, the DFOs other than the DFO that contains the primary table will use a DOP of 4; when the statement queries the index table, the DFOs other than the DFO that contains the index table will use a DOP of 2.
If an SQL statement involves multiple tables, the DOP of the entire execution plan will be the maximum DOP specified by the PARALLEL hint.
Specify the DOP by using the PARALLEL HINT
You can use the global PARALLEL hint to specify the DOP for an entire SQL query statement, and you can use the table-level PARALLEL hint to specify the DOP for a specific table. If both hints are specified in one SQL query statement, the table-level hint overrides the global hint.
When the PARALLEL hint is added to multiple tables, the DOP of each DFO is determined by the PARALLEL value of the table in the DFO. If a DFO contains multiple tables, the DOP of the DFO is the maximum PARALLEL value among the tables.
GLOBAL 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
Table-level 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
If you use the preceding hint for a DML statement, the hint only enables parallel execution for the query part of the DML statement, while the write part remains to be executed serially. If you want the write part to be executed in parallel, you must add the HINT ENABLE_PARALLEL_DML, for example:
INSERT /*+ parallel(3) enable_parallel_dml */ INTO t3 SELECT * FROM t1;
Notice
Parallel DML requires the global parallel hint. If you specify only the table-level parallel hint, parallel DML cannot be enabled for writing data. For example, the following SQL statement does not enable parallel DML: INSERT /*+ parallel(t3 3) enable_parallel_dml */ INTO t3 SELECT * FROM t1;
Set the DOP for a session
Once the DOP is set for a session, the DOP for all statements in the session is set to the specified value. Note that the SQL statements that retrieve single rows also will be executed with the specified DOP, which may lead to performance degradation.
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 3;
For DML statements, the preceding command only enables parallel execution for the query part of the DML statements. The write part remains sequential. To make the write part parallel as well, use the following command:
ALTER SESSION FORCE PARALLEL DML PARALLEL 3;
To disable session-level parallel execution, use the following command:
ALTER SESSION DISABLE PARALLEL QUERY;
Automatic DOP
For more information about automatic DOP, see Auto DOP.
DOP precedence
TABLE HINT > global hint > session-level DOP > table-level DOP
Compare the global hint and the table hint. The query plan shows that the global hint does not take effect when the table hint is specified.
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
Compare the session-level DOP and the table hint. The query plan shows that the session-level DOP does not take effect when the table hint is specified.
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
Compare the session-level DOP and the table-level DOP. The query plan shows that the table-level DOP has a higher priority than the session-level 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