6.3.4显示执行计划:示例
这些示例显示了显示执行计划的不同方式。
本节包含以下主题:
- 自定义PLAN_TABLE输出:如果已指定语句标识符,则可以编写自己的脚本来查询
PLAN_TABLE。 - 显示并行执行计划:并行查询的示例计划在重要方面不同于串行查询的计划。
- 显示位图索引计划:使用位图索引的示例索引行源出现在
EXPLAIN PLAN输出中,并带有BITMAP表示索引类型的单词。 - 显示结果缓存计划:示例:
当查询包含result_cache提示时,ResultCache运算符将插入到执行计划中。 - 显示计划分区对象:示例 :使用
EXPLAIN PLAN,以确定Oracle数据库如何访问特定查询分区对象。
6.3.4.1自定义PLAN_TABLE输出
如果您指定了语句标识符,则可以编写自己的脚本来查询PLAN_TABLE。
例如:
- 从ID = 0开始并给出
STATEMENT_ID。 - 使用
CONNECT BY子句将树从父级移到子级,连接键为STATEMENT_ID = PRIOR STATMENT_ID和PARENT_ID = PRIOR ID。 - 使用伪列
LEVEL(与关联CONNECT BY)使子代缩进。SELECT cardinality "Rows", lpad(' ',level-1)||operation||' '||options||' '||object_name "Plan" FROM PLAN_TABLE CONNECT BY prior id = parent_id AND prior statement_id = statement_id START WITH id = 0 AND statement_id = 'st1' ORDER BY id; Rows Plan ------- ---------------------------------------- SELECT STATEMENT TABLE ACCESS FULL EMPLOYEES将
NULL在Rows列指示优化器不会对表中的任何统计数据。分析表显示以下内容:Rows Plan ------- ---------------------------------------- 16957 SELECT STATEMENT 16957 TABLE ACCESS FULL EMPLOYEES您也可以选择
COST。这对于比较执行计划或了解优化器为何选择一个执行计划而不是另一个执行计划很有用。注意:
这些简化的示例对于递归SQL无效。
6.3.4.2显示并行执行计划:示例
并行查询计划与串行查询计划在重要方面有所不同。
本节包含以下主题:
- 关于EXPLAIN PLAN和并行查询
调整并行查询的开始非常类似于通过选择驱动表进行非并行查询调整的练习。但是,支配选择的规则是不同的。 - 使用EXPLAIN PLAN查看并行查询:示例与并行查询一起
使用EXPLAIN PLAN时,数据库将编译并执行一个并行计划。该计划是通过分配特定于QC计划中并行支持的行源而从串行计划中得出的。
6.3.4.2.1关于EXPLAIN PLAN和并行查询
调整并行查询的开始非常类似于通过选择驱动表进行非并行查询调整的练习。但是,管理选择的规则是不同的。
在串行情况下,最佳驱动表在应用限制条件后产生的行数最少。数据库使用非唯一索引将少量的行连接到较大的表。
例如,考虑表层次结构组成的customer,account和transaction。
图6-1表层次结构
在此示例中,customer是最小的表,而是transaction最大的表。典型的OLTP查询检索有关特定客户帐户的交易信息。查询从customer表驱动。目标是最小化逻辑I / O,这通常会最小化其他关键资源,包括物理I / O和CPU时间。
对于并行查询,驱动表通常是最大的表。在这种情况下,使用并行查询可能不会很有效,因为只能访问每个表中的几行。但是,如果有必要确定上个月进行过某种交易的所有客户该怎么办?从transaction表驱动会更有效,因为表上没有限制条件customer。数据库将transaction表中的行连接到account表,然后将结果集最终连接到customer表。在这种情况下,accountand customer表上使用的可能是高度选择性的主键或唯一索引,而不是第一个查询中使用的非唯一索引。因为transaction表很大并且列不是选择性的,因此使用从transaction表进行并行查询驱动将是有益的。
并行操作包括以下内容:
PARALLEL_TO_PARALLELPARALLEL_TO_SERIALPARALLEL_TO_SERIAL操作总是第一步,当查询协调从并行操作消耗的行发生的步骤。此查询中未发生的另一种操作类型是SERIAL操作。如果发生这些类型的操作,请考虑使其并行操作以提高性能,因为它们也是潜在的瓶颈。PARALLEL_FROM_SERIALPARALLEL_TO_PARALLEL如果每个步骤中的工作量相对相等,则这些
PARALLEL_TO_PARALLEL操作通常会产生最佳性能。PARALLEL_COMBINED_WITH_CHILDPARALLEL_COMBINED_WITH_PARENTPARALLEL_COMBINED_WITH_PARENT当数据库执行同时与父步骤的步骤发生操作。
如果并行步骤产生许多行,那么QC可能无法像产生它们一样快地消耗掉这些行。改善这种情况无能为力。
也可以看看:
该OTHER_TAG列“ PLAN_TABLE列 ”
6.3.4.2.2使用EXPLAIN PLAN查看并行查询:示例
EXPLAIN PLAN与并行查询一起使用时,数据库将编译并执行一个并行计划。该计划是通过分配特定于QC计划中并行支持的行源而从串行计划中得出的。
将两个并行执行服务器集PQ模型所需的表队列行源(PX Send和PX Receive),粒度迭代器和缓冲区排序直接插入并行计划中。对于并行执行的所有并行执行服务器,或者对于串行执行的QC,该计划都是相同的计划。
示例6-4并行查询解释计划
以下简单示例说明EXPLAIN PLAN了并行查询的:
CREATE TABLE emp2 AS SELECT * FROM employees;
ALTER TABLE emp2 PARALLEL 2;
EXPLAIN PLAN FOR
SELECT SUM(salary)
FROM emp2
GROUP BY department_id;
SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());
------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows| Bytes |Cost %CPU| TQ |IN-OUT| PQ Distrib |
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 107 | 2782 | 3 (34) | | | |
| 1 | PX COORDINATOR | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10001 | 107 | 2782 | 3 (34) | Q1,01 | P->S | QC (RAND) |
| 3 | HASH GROUP BY | | 107 | 2782 | 3 (34) | Q1,01 | PCWP | |
| 4 | PX RECEIVE | | 107 | 2782 | 3 (34) | Q1,01 | PCWP | |
| 5 | PX SEND HASH | :TQ10000 | 107 | 2782 | 3 (34) | Q1,00 | P->P | HASH |
| 6 | HASH GROUP BY | | 107 | 2782 | 3 (34) | Q1,00 | PCWP | |
| 7 | PX BLOCK ITERATOR | | 107 | 2782 | 2 (0) | Q1,00 | PCWP | |
| 8 | TABLE ACCESS FULL| EMP2 | 107 | 2782 | 2 (0) | Q1,00 | PCWP | |
------------------------------------------------------------------------------------------------
一组并行执行服务器并行扫描EMP2,而第二组并行执行服务器的聚合GROUP BY。
PX BLOCK ITERATOR行源表示分裂表中的EMP2成片来划分并行处理服务器之间的扫描工作量。
PX SEND和PX RECEIVE行源表示两套并行处理服务器为行从平行扫描向上流动,通过获得重新分区连接管HASH表队列,然后通过读出并聚集在顶部集。
PX SEND QC行源表示被发送到QC在随机(RAND)顺序聚合值。
PX COORDINATOR 行源表示QC或查询协调器,它控制并计划在计划树中显示在其下方的并行计划。
6.3.4.3显示位图索引计划:示例
使用位图索引的索引行源出现在EXPLAIN PLAN输出中,并带有BITMAP表示索引类型的单词。
示例6-5具有位图索引的EXPLAIN PLAN
在此示例中,谓词c1=2产生一个位图,可以从该位图中减去。从该位图c2=6中减去位图中的位。同样,将的位图中的位相c2 IS NULL减,解释了为什么MINUS计划中有两个行源。该NULL减法是必要的语义的正确性,除非列有一个NOT NULL约束。该TO ROWIDS选项生成表访问所需的行标识。
注意:
使用位图连接索引的查询指示位图连接索引访问路径。位图连接索引的操作与位图索引相同。
EXPLAIN PLAN FOR SELECT *
FROM t
WHERE c1 = 2
AND c2 <> 6
OR c3 BETWEEN 10 AND 20;
SELECT STATEMENT
TABLE ACCESS T BY INDEX ROWID
BITMAP CONVERSION TO ROWID
BITMAP OR
BITMAP MINUS
BITMAP MINUS
BITMAP INDEX C1_IND SINGLE VALUE
BITMAP INDEX C2_IND SINGLE VALUE
BITMAP INDEX C2_IND SINGLE VALUE
BITMAP MERGE
BITMAP INDEX C3_IND RANGE SCAN
父主题: 显示执行计划:示例
6.3.4.4显示结果缓存计划:示例
当查询中包含result_cache提示时,会将ResultCache运算符插入执行计划中。
例如,考虑以下查询:
SELECT /*+ result_cache */ deptno, avg(sal)
FROM emp
GROUP BY deptno;
要查看EXPLAIN PLAN此查询的,请使用以下命令:
EXPLAIN PLAN FOR
SELECT /*+ result_cache */ deptno, avg(sal)
FROM emp
GROUP BY deptno;
SELECT PLAN_TABLE_OUTPUT FROM TABLE (DBMS_XPLAN.DISPLAY());
该EXPLAIN PLAN查询的输出应类似于以下内容:
--------------------------------------------------------------------------------
|Id| Operation | Name |Rows|Bytes|Cost(%CPU)|Time |
--------------------------------------------------------------------------------
|0| SELECT STATEMENT | | 11 | 77 | 4 (25)| 00:00:01|
|1| RESULT CACHE |b06ppfz9pxzstbttpbqyqnfbmy| | | | |
|2| HASH GROUP BY | | 11 | 77 | 4 (25)| 00:00:01|
|3| TABLE ACCESS FULL| EMP |107 | 749| 3 (0) | 00:00:01|
--------------------------------------------------------------------------------
在此EXPLAIN PLAN,在ResultCache操作者通过其标识CacheId,这是b06ppfz9pxzstbttpbqyqnfbmy。现在,您可以V$RESULT_CACHE_OBJECTS使用this 在视图上运行查询CacheId。
6.3.4.5显示分区对象的计划:示例
使用EXPLAIN PLAN以确定Oracle数据库存取如何被分割为特定查询的对象。
修剪后访问的分区显示在PARTITION START和PARTITION STOP列中。
范围分区的行源名称为PARTITION RANGE。
对于哈希分区,行源名称为PARTITION HASH。
如果DISTRIBUTION联接表之一的计划表的列包含,则使用部分分区联接实现联接PARTITION(KEY)。如果已连接的表之一在其连接列上进行分区并且该表已并行化,则可以进行部分分区连接。
如果分区行源出现在EXPLAIN PLAN输出中的连接行源之前,则使用完整的分区智能连接来实现连接。仅当两个联接表在各自的联接列上均分时,才可以进行完全分区联接。以下是几种分区类型的执行计划示例。
本节包含以下主题:
- 使用EXPLAIN PLAN显示范围和哈希分区:示例
此示例说明使用emp_range表的修剪,该表按上的range进行分区hire_date。 - 使用复合分区对象修剪信息:示例
为了说明Oracle数据库如何显示复合分区对象修剪信息,请考虑使用tableemp_comp。它在on上进行范围分区,hiredate并由hash上再分区deptno。 - 部分分区明智连接的
示例在这些示例中,PQ_DISTRIBUTE提示显式强制进行部分分区明智的连接,因为查询优化器可以根据此查询中的成本选择其他计划。 - 完整分区明智连接的
示例在此示例中,emp_comp并且dept_hash在其哈希分区列上进行了连接,从而可以使用完整分区明智的连接。 - INLIST ITERATOR和EXPLAIN PLAN
的示例如果索引实现了-list谓词,则INLIST ITERATOR操作将出现在EXPLAIN PLAN输出中IN。 - 域索引和解释计划的示例
您可以EXPLAIN PLAN用来导出用户定义的域索引的CPU和I / O成本。
父主题: 显示执行计划:示例
6.3.4.5.1使用EXPLAIN PLAN显示范围和哈希分区:示例
本示例说明了使用emp_range表进行修剪的情况,该表按上的range进行了分区hire_date。
假设存在表employees和departments来自Oracle数据库的示例架构。
CREATE TABLE emp_range
PARTITION BY RANGE(hire_date)
(
PARTITION emp_p1 VALUES LESS THAN (TO_DATE('1-JAN-1992','DD-MON-YYYY')),
PARTITION emp_p2 VALUES LESS THAN (TO_DATE('1-JAN-1994','DD-MON-YYYY')),
PARTITION emp_p3 VALUES LESS THAN (TO_DATE('1-JAN-1996','DD-MON-YYYY')),
PARTITION emp_p4 VALUES LESS THAN (TO_DATE('1-JAN-1998','DD-MON-YYYY')),
PARTITION emp_p5 VALUES LESS THAN (TO_DATE('1-JAN-2001','DD-MON-YYYY'))
)
AS SELECT * FROM employees;
对于第一个示例,请考虑以下语句:
EXPLAIN PLAN FOR
SELECT * FROM emp_range;
Oracle数据库显示类似于以下内容:
--------------------------------------------------------------------
|Id| Operation | Name |Rows| Bytes|Cost|Pstart|Pstop|
--------------------------------------------------------------------
| 0| SELECT STATEMENT | | 105| 13965 | 2 | | |
| 1| PARTITION RANGE ALL| | 105| 13965 | 2 | 1 | 5 |
| 2| TABLE ACCESS FULL | EMP_RANGE | 105| 13965 | 2 | 1 | 5 |
--------------------------------------------------------------------
数据库在表访问行源的顶部创建一个分区行源。遍历要访问的分区集。在此示例中,分区迭代器涵盖了所有分区(选项ALL),因为未使用谓词进行修剪。show 的PARTITION_START和PARTITION_STOP列PLAN_TABLE显示从1到5的所有分区的访问权限。
对于下一个示例,请考虑以下语句:
EXPLAIN PLAN FOR
SELECT *
FROM emp_range
WHERE hire_date >= TO_DATE('1-JAN-1996','DD-MON-YYYY');
-----------------------------------------------------------------------
| Id | Operation | Name |Rows|Bytes|Cost|Pstart|Pstop|
-----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 3 | 399 | 2 | | |
| 1 | PARTITION RANGE ITERATOR| | 3 | 399 | 2 | 4 | 5 |
| *2 | TABLE ACCESS FULL |EMP_RANGE| 3 | 399 | 2 | 4 | 5 |
-----------------------------------------------------------------------
在前面的示例中,分区行源从分区4迭代到5,这是因为数据库使用on谓词来修剪其他分区hire_date。
最后,考虑以下语句:
EXPLAIN PLAN FOR
SELECT *
FROM emp_range
WHERE hire_date < TO_DATE('1-JAN-1992','DD-MON-YYYY');
-----------------------------------------------------------------------
| Id | Operation | Name |Rows|Bytes|Cost|Pstart|Pstop|
-----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 133 | 2 | | |
| 1 | PARTITION RANGE SINGLE| | 1 | 133 | 2 | 1 | 1 |
|* 2 | TABLE ACCESS FULL | EMP_RANGE | 1 | 133 | 2 | 1 | 1 |
-----------------------------------------------------------------------
在前面的示例中,仅分区1在编译时被访问和知道;因此,不需要分区行源。
注意:
Oracle Database对哈希分区对象显示相同的信息,除了分区行源名称PARTITION HASH不是PARTITION RANGE。同样,对于散列分区,只能使用相等或IN-list谓词进行修剪。
父主题: 显示分区对象的计划:示例
6.3.4.5.2使用复合分区对象修剪信息:示例
为了说明Oracle数据库如何显示组合分区对象的修剪信息,请考虑使用table emp_comp。它在on上进行范围分区,hiredate并由hash上再分区deptno。
CREATE TABLE emp_comp PARTITION BY RANGE(hire_date)
SUBPARTITION BY HASH(department_id) SUBPARTITIONS 3
(
PARTITION emp_p1 VALUES LESS THAN (TO_DATE('1-JAN-1992','DD-MON-YYYY')),
PARTITION emp_p2 VALUES LESS THAN (TO_DATE('1-JAN-1994','DD-MON-YYYY')),
PARTITION emp_p3 VALUES LESS THAN (TO_DATE('1-JAN-1996','DD-MON-YYYY')),
PARTITION emp_p4 VALUES LESS THAN (TO_DATE('1-JAN-1998','DD-MON-YYYY')),
PARTITION emp_p5 VALUES LESS THAN (TO_DATE('1-JAN-2001','DD-MON-YYYY'))
)
AS SELECT * FROM employees;
对于第一个示例,请考虑以下语句:
EXPLAIN PLAN FOR
SELECT * FROM emp_comp;
-----------------------------------------------------------------------
|Id| Operation | Name | Rows | Bytes |Cost|Pstart|Pstop|
-----------------------------------------------------------------------
| 0| SELECT STATEMENT | | 10120 | 1314K| 78 | | |
| 1| PARTITION RANGE ALL| | 10120 | 1314K| 78 | 1 | 5 |
| 2| PARTITION HASH ALL| | 10120 | 1314K| 78 | 1 | 3 |
| 3| TABLE ACCESS FULL| EMP_COMP | 10120 | 1314K| 78 | 1 | 15 |
-----------------------------------------------------------------------
此示例显示了Oracle数据库访问组合对象的所有分区的所有子分区时的计划。
为此,数据库使用两个分区行源:一个用于遍历分区的范围分区行源,以及一个用于遍历每个访问分区的子分区的哈希分区行源。
在以下示例中,范围分区行源从分区1迭代到5,因为数据库不执行修剪。在每个分区内,哈希分区行源在当前分区的子分区1到3上进行迭代。结果,表访问行源访问子分区1到15。换句话说,数据库访问组合对象的所有子分区。
EXPLAIN PLAN FOR
SELECT *
FROM emp_comp
WHERE hire_date = TO_DATE('15-FEB-1998', 'DD-MON-YYYY');
-----------------------------------------------------------------------
| Id | Operation | Name |Rows|Bytes |Cost|Pstart|Pstop|
-----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 20 | 2660 | 17 | | |
| 1 | PARTITION RANGE SINGLE| | 20 | 2660 | 17 | 5 | 5 |
| 2 | PARTITION HASH ALL | | 20 | 2660 | 17 | 1 | 3 |
|* 3 | TABLE ACCESS FULL | EMP_COMP | 20 | 2660 | 17 | 13 | 15 |
-----------------------------------------------------------------------
在前面的示例中,仅访问最后一个分区,即分区5。该分区在编译时是已知的,因此数据库无需在计划中显示它。哈希分区行源显示了对该分区内所有子分区的访问;也就是子分区1到3,它转换为emp_comp表的子分区13到15 。
现在考虑以下语句:
EXPLAIN PLAN FOR
SELECT *
FROM emp_comp
WHERE department_id = 20;
------------------------------------------------------------------------
| Id | Operation |Name |Rows | Bytes |Cost|Pstart|Pstop|
------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 101 | 13433 | 78 | | |
| 1 | PARTITION RANGE ALL | | 101 | 13433 | 78 | 1 | 5 |
| 2 | PARTITION HASH SINGLE| | 101 | 13433 | 78 | 3 | 3 |
|* 3 | TABLE ACCESS FULL | EMP_COMP | 101 | 13433 | 78 | | |
------------------------------------------------------------------------
在前面的示例中,该谓词deptno=20允许对每个分区内的哈希维度进行修剪。因此,Oracle数据库仅需要访问一个子分区。该子分区的编号在编译时是已知的,因此不需要哈希分区行源。
最后,考虑以下语句:
VARIABLE dno NUMBER;
EXPLAIN PLAN FOR
SELECT *
FROM emp_comp
WHERE department_id = :dno;
-----------------------------------------------------------------------
| Id| Operation | Name |Rows| Bytes |Cost|Pstart|Pstop|
-----------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 101| 13433 | 78 | | |
| 1 | PARTITION RANGE ALL | | 101| 13433 | 78 | 1 | 5 |
| 2 | PARTITION HASH SINGLE| | 101| 13433 | 78 | KEY | KEY |
|*3 | TABLE ACCESS FULL | EMP_COMP | 101| 13433 | 78 | | |
-----------------------------------------------------------------------
最后两个示例相同,除了department_id=:dnoreplaces deptno=20。在后一种情况下,子分区号在编译时未知,并且分配了哈希分区行源。该选项SINGLE适用于此行源,因为Oracle数据库仅访问每个分区内的一个子分区。在步骤2中,PARTITION_ START和PARTITION_ STOP都设置为KEY。此值表示Oracle数据库在运行时确定子分区的数量。
父主题: 显示分区对象的计划:示例
6.3.4.5.3部分分区明确联接的示例
在这些示例中,PQ_DISTRIBUTE由于查询优化器可能已基于此查询中的成本选择了不同的计划,因此该提示明确地强制进行部分分区连接。
示例6-6带有分区的部分分区明智联接
emp_range_did在分区列上联接department_id并对其进行并行化。数据库可以使用部分分区联接,因为dept2表未分区。Oracle数据库dept2在连接之前对表进行动态分区。CREATE TABLE dept2 AS SELECT * FROM departments;
ALTER TABLE dept2 PARALLEL 2;
CREATE TABLE emp_range_did PARTITION BY RANGE(department_id)
(PARTITION emp_p1 VALUES LESS THAN (150),
PARTITION emp_p5 VALUES LESS THAN (MAXVALUE) )
AS SELECT * FROM employees;
ALTER TABLE emp_range_did PARALLEL 2;
EXPLAIN PLAN FOR
SELECT /*+ PQ_DISTRIBUTE(d NONE PARTITION) ORDERED */ e.last_name,
d.department_name
FROM emp_range_did e, dept2 d
WHERE e.department_id = d.department_id;
------------------------------------------------------------------------------------------------
|Id| Operation |Name |Row|Byte|Cost|Pstart|Pstop|TQ|IN-OUT|PQ Distrib|
------------------------------------------------------------------------------------------------
| 0| SELECT STATEMENT | |284 |16188|6 | | | | | |
| 1| PX COORDINATOR | | | | | | | | | |
| 2| PX SEND QC (RANDOM) |:TQ10001 |284 |16188|6 | | | Q1,01 |P->S |QC (RAND) |
|*3| HASH JOIN | |284 |16188|6 | | | Q1,01 |PCWP | |
| 4| PX PARTITION RANGE ALL | |284 |7668 |2 | 1 | 2 | Q1,01 |PCWC | |
| 5| TABLE ACCESS FULL |EMP_RANGE_DID|284 |7668 |2 | 1 | 2 | Q1,01 |PCWP | |
| 6| BUFFER SORT | | | | | | | Q1,01 |PCWC | |
| 7| PX RECEIVE | | 21 | 630 |2 | | | Q1,01 |PCWP | |
| 8| PX SEND PARTITION (KEY)|:TQ10000 | 21 | 630 |2 | | | |S->P |PART (KEY)|
| 9| TABLE ACCESS FULL |DEPT2 | 21 | 630 |2 | | | | | |
------------------------------------------------------------------------------------------------
执行计划显示,该表dept2被串行扫描,并且所有具有相同分区列值的行都emp_range_did (department_id)通过PART (KEY)或分区键表队列发送到执行部分分区联接的同一并行执行服务器。
示例6-7具有复合分区的部分分区明智连接
在以下示例中,emp_comp在分区列上被联接并被并行化,由于dept2未分区,因此可以使用部分按分区联接。数据库dept2在加入之前动态分区。
ALTER TABLE emp_comp PARALLEL 2;
EXPLAIN PLAN FOR
SELECT /*+ PQ_DISTRIBUTE(d NONE PARTITION) ORDERED */ e.last_name,
d.department_name
FROM emp_comp e, dept2 d
WHERE e.department_id = d.department_id;
SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY());
------------------------------------------------------------------------------------------------
| Id| Operation | Name |Rows |Bytes |Cost|Pstart|Pstop|TQ |IN-OUT|PQ Distrib|
------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 445 | 17800 | 5 | | | | | |
| 1 | PX COORDINATOR | | | | | | | | | |
| 2 | PX SEND QC (RANDOM) |:TQ10001| 445 | 17800 | 5 | | | Q1,01 | P->S | QC (RAND)|
|*3 | HASH JOIN | | 445 | 17800 | 5 | | | Q1,01 | PCWP | |
| 4 | PX PARTITION RANGE ALL | | 107 | 1070 | 3 | 1 | 5 | Q1,01 | PCWC | |
| 5 | PX PARTITION HASH ALL | | 107 | 1070 | 3 | 1 | 3 | Q1,01 | PCWC | |
| 6 | TABLE ACCESS FULL |EMP_COMP| 107 | 1070 | 3 | 1 | 15| Q1,01 | PCWP | |
| 7 | PX RECEIVE | | 21 | 630 | 1 | | | Q1,01 | PCWP | |
| 8 | PX SEND PARTITION (KEY)|:TQ10000| 21 | 630 | 1 | | | Q1,00 | P->P |PART (KEY)|
| 9 | PX BLOCK ITERATOR | | 21 | 630 | 1 | | | Q1,00 | PCWC | |
|10 | TABLE ACCESS FULL |DEPT2 | 21 | 630 | 1 | | | Q1,00 | PCWP | |
------------------------------------------------------------------------------------------------
该计划表明,优化器从两列之一中选择了部分分区连接。该PX SEND节点类型是PARTITION (KEY)与PQ Distrib列包含文本PART (KEY),或分区键。这意味着dept2将根据联接列department_id对表进行重新分区,以将其发送到执行扫描EMP_COMP和联接的并行执行服务器。
6.3.4.5.4全分区明智连接的示例
在此示例中,emp_comp和dept_hash在其哈希分区列上进行了联接,从而可以使用完整的分区联接。
PARTITION HASH在计划表输出中,行源显示在连接行源的顶部。
CREATE TABLE dept_hash
PARTITION BY HASH(department_id)
PARTITIONS 3
PARALLEL 2
AS SELECT * FROM departments;
EXPLAIN PLAN FOR
SELECT /*+ PQ_DISTRIBUTE(e NONE NONE) ORDERED */ e.last_name,
d.department_name
FROM emp_comp e, dept_hash d
WHERE e.department_id = d.department_id;
------------------------------------------------------------------------------------------------
|Id| Operation | Name |Rows|Bytes|Cost|Pstart|Pstop|TQ |IN-OUT|PQ Distrib|
------------------------------------------------------------------------------------------------
| 0| SELECT STATEMENT | | 106 | 2544 | 8 | | | | | |
| 1| PX COORDINATOR | | | | | | | | | |
| 2| PX SEND QC (RANDOM) | :TQ10000 | 106 | 2544 | 8 | | | Q1,00 | P->S |QC (RAND)|
| 3| PX PARTITION HASH ALL | | 106 | 2544 | 8 | 1 | 3 | Q1,00 | PCWC | |
|*4| HASH JOIN | | 106 | 2544 | 8 | | | Q1,00 | PCWP | |
| 5| PX PARTITION RANGE ALL| | 107 | 1070 | 3 | 1 | 5 | Q1,00 | PCWC | |
| 6| TABLE ACCESS FULL | EMP_COMP | 107 | 1070 | 3 | 1 | 15 | Q1,00 | PCWP | |
| 7| TABLE ACCESS FULL | DEPT_HASH | 27 | 378 | 4 | 1 | 3 | Q1,00 | PCWP | |
------------------------------------------------------------------------------------------------该PX PARTITION HASH行源的顶部出现在加入该计划表输出行源
而PX PARTITION RANGE行源出现在扫描的emp_comp。每个并行执行服务器执行的整个哈希分区emp_comp与的整个分区的联接dept_hash。
6.3.4.5.5 INLIST ITERATOR和说明计划的示例
的INLIST ITERATOR操作出现在EXPLAIN PLAN如果索引工具的输出IN-list谓词。
考虑以下语句:
SELECT * FROM emp WHERE empno IN (7876, 7900, 7902);
该EXPLAIN PLAN输出显示如下:
OPERATION OPTIONS OBJECT_NAME
---------------- --------------- --------------
SELECT STATEMENT
INLIST ITERATOR
TABLE ACCESS BY ROWID EMP
INDEX RANGE SCAN EMP_EMPNO
该INLIST ITERATOR操作针对IN-list谓词中的每个值迭代计划中的下一个操作。以下各节描述了IN分区表和索引的-list列的三种可能类型。
本节包含以下主题:
- 当IN-List列是索引列时:示例 如果
IN-list列empno是索引列而不是分区列,则IN-list运算符出现在表操作之前但计划中的分区操作之后。 - 当IN列表列是索引列和分区列时:示例 如果
empno是索引列和分区列,则计划INLIST ITERATOR在分区操作之前包含一个操作。 - 当IN-List列为分区列时:示例 如果
empno为分区列且不存在索引,则不对INLIST ITERATOR分配任何操作。
父主题: 显示分区对象的计划:示例
6.3.4.5.5.1当IN-List列是索引列时:示例
如果IN-list列empno是索引列而不是分区列,则IN-list运算符将出现在表操作之前,计划中分区操作之后。
OPERATION OPTIONS OBJECT_NAME PARTIT_START PARTITION_STOP
---------------- ------------ ----------- ------------ --------------
SELECT STATEMENT
PARTITION RANGE ALL KEY(INLIST) KEY(INLIST)
INLIST ITERATOR <--------- 在表操作之前但计划中的分区操作之后
TABLE ACCESS BY LOCAL INDEX ROWID EMP KEY(INLIST) KEY(INLIST)
INDEX RANGE SCAN EMP_EMPNO KEY(INLIST) KEY(INLIST)
在KEY(INLIST)该分区的开始和停止的键指定的指定,一个IN-list谓词出现在索引启动和停止的键。
6.3.4.5.5.2当IN-List列是索引和分区列时:示例
如果empno是索引和分区列,则计划INLIST ITERATOR在分区操作之前包含一个操作。
OPERATION OPTIONS OBJECT_NAME PARTITION_START PARTITION_STOP
---------------- ------------ ----------- --------------- --------------
SELECT STATEMENT
INLIST ITERATOR <---------分区操作之前包含一个操作
PARTITION RANGE ITERATOR KEY(INLIST) KEY(INLIST)
TABLE ACCESS BY LOCAL INDEX ROWID EMP KEY(INLIST) KEY(INLIST)
INDEX RANGE SCAN EMP_EMPNO KEY(INLIST) KEY(INLIST)父主题: INLIST ITERATOR和EXPLAIN PLAN的示例
6.3.4.5.5.3当IN-List列是分区列时:示例
如果empno是分区列并且不存在索引,则不INLIST ITERATOR分配任何操作。
OPERATION OPTIONS OBJECT_NAME PARTITION_START PARTITION_STOP
---------------- ------------ ----------- --------------- --------------
SELECT STATEMENT
PARTITION RANGE INLIST KEY(INLIST) KEY(INLIST) <---------不对INLIST ITERATOR分配任何操作 , 也没有分区
TABLE ACCESS FULL EMP KEY(INLIST) KEY(INLIST)
如果emp_empno是位图索引,则计划如下:
OPERATION OPTIONS OBJECT_NAME
---------------- --------------- --------------
SELECT STATEMENT
INLIST ITERATOR
TABLE ACCESS BY INDEX ROWID EMP
BITMAP CONVERSION TO ROWIDS
BITMAP INDEX SINGLE VALUE EMP_EMPNO6.3.4.5.6域索引和说明计划示例
您可以EXPLAIN PLAN用来导出域索引的用户定义的CPU和I / O成本。
EXPLAIN PLAN在的OTHER列中显示域索引统计信息PLAN_TABLE。例如,假定表emp具有用户定义的运算符CONTAINS,该运算符emp_resume在resume列上具有域索引,并且索引类型emp_resume支持operator CONTAINS。您说明以下查询的计划:
SELECT * FROM emp WHERE CONTAINS(resume, 'Oracle') = 1
该数据库可以显示以下计划:
OPERATION OPTIONS OBJECT_NAME OTHER
----------------- ----------- ------------ ----------------
SELECT STATEMENT
TABLE ACCESS BY ROWID EMP
DOMAIN INDEX EMP_RESUME CPU: 300, I/O: 4



