暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 19C 显示执行计划:示例

原创 Asher.HU 2021-02-04
1395

6.3.4显示执行计划:示例

这些示例显示了显示执行计划的不同方式。

本节包含以下主题:


6.3.4.1自定义PLAN_TABLE输出

如果您指定了语句标识符,则可以编写自己的脚本来查询PLAN_TABLE

例如:

  • 从ID = 0开始并给出STATEMENT_ID
  • 使用CONNECT BY子句将树从父级移到子级,连接键为STATEMENT_ID = PRIOR STATMENT_IDPARENT_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
    

    NULLRows列指示优化器不会对表中的任何统计数据。分析表显示以下内容:

       Rows Plan
    ------- ----------------------------------------
      16957 SELECT STATEMENT
      16957  TABLE ACCESS FULL EMPLOYEES
    

    您也可以选择COST这对于比较执行计划或了解优化器为何选择一个执行计划而不是另一个执行计划很有用。

    注意:

    这些简化的示例对于递归SQL无效。

 

6.3.4.2显示并行执行计划:示例

并行查询计划与串行查询计划在重要方面有所不同。

本节包含以下主题:

 

6.3.4.2.1关于EXPLAIN PLAN和并行查询

调整并行查询的开始非常类似于通过选择驱动表进行非并行查询调整的练习。但是,管理选择的规则是不同的。

在串行情况下,最佳驱动表在应用限制条件后产生的行数最少。数据库使用非唯一索引将少量的行连接到较大的表。

例如,考虑表层次结构组成的customeraccounttransaction

图6-1表层次结构

在此示例中,customer是最小的表,而是transaction最大的表。典型的OLTP查询检索有关特定客户帐户的交易信息。查询从customer驱动目标是最小化逻辑I / O,这通常会最小化其他关键资源,包括物理I / O和CPU时间。

对于并行查询,驱动表通常是最大的表。这种情况下使用并行查询可能不会很有效,因为只能访问每个表中的几行。但是,如果有必要确定上个月进行过某种交易的所有客户该怎么办?transaction驱动会更有效,因为表上没有限制条件customer数据库将transaction表中的行连接account表,然后将结果集最终连接到customer表。在这种情况下,accountand customer表上使用的可能是高度选择性的主键或唯一索引,而不是第一个查询中使用的非唯一索引。因为transaction表很大并且列不是选择性的,因此使用从transaction表进行并行查询驱动将是有益的

并行操作包括以下内容:

  • PARALLEL_TO_PARALLEL
  • PARALLEL_TO_SERIAL

        PARALLEL_TO_SERIAL操作总是第一步,当查询协调从并行操作消耗的行发生的步骤。此查询中未发生的另一种操作类型是SERIAL操作。如果发生这些类型的操作,请考虑使其并行操作以提高性能,因为它们也是潜在的瓶颈。

  • PARALLEL_FROM_SERIAL
  • PARALLEL_TO_PARALLEL

    如果每个步骤中的工作量相对相等,则这些PARALLEL_TO_PARALLEL操作通常会产生最佳性能。

  • PARALLEL_COMBINED_WITH_CHILD
  • PARALLEL_COMBINED_WITH_PARENT

     PARALLEL_COMBINED_WITH_PARENT当数据库执行同时与父步骤的步骤发生操作。

如果并行步骤产生许多行,那么QC可能无法像产生它们一样快地消耗掉这些行。改善这种情况无能为力。

也可以看看:

OTHER_TAG PLAN_TABLE列 

 

6.3.4.2.2使用EXPLAIN PLAN查看并行查询:示例

EXPLAIN PLAN与并行查询一起使用时,数据库将编译并执行一个并行计划。该计划是通过分配特定于QC计划中并行支持的行源而从串行计划中得出的。

两个并行执行服务器集PQ模型所需的表队列行源(PX SendPX 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 SENDPX 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 STARTPARTITION STOP列中。

范围分区的行源名称为PARTITION RANGE

对于哈希分区,行源名称为PARTITION HASH


如果DISTRIBUTION联接表之一的计划表列包含,则使用部分分区联接实现联接PARTITION(KEY)如果已连接的表之一在其连接列上进行分区并且该表已并行化,则可以进行部分分区连接。

如果分区行源出现在EXPLAIN PLAN输出中的连接行源之前,则使用完整的分区智能连接来实现连接仅当两个联接表在各自的联接列上均分时,才可以进行完全分区联接。以下是几种分区类型的执行计划示例。

本节包含以下主题:

父主题: 显示执行计划:示例

6.3.4.5.1使用EXPLAIN PLAN显示范围和哈希分区:示例

本示例说明了使用emp_range表进行修剪的情况,该表按上的range进行了分区hire_date

假设存在表employeesdepartments来自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_STARTPARTITION_STOPPLAN_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_ STARTPARTITION_ 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_compdept_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列的三种可能类型

本节包含以下主题:

父主题: 显示分区对象的计划:示例

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_EMPNO



6.3.4.5.6域索引和说明计划示例

您可以EXPLAIN PLAN用来导出域索引的用户定义的CPU和I / O成本。

EXPLAIN PLAN在的OTHER列中显示域索引统计信息PLAN_TABLE例如,假定表emp具有用户定义的运算符CONTAINS,该运算符emp_resumeresume具有域索引,并且索引类型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
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论