12c新增并行索引扫描

栏目: 数据库 · Oracle · 发布时间: 5年前

Oracle在12c之前对于索引范围扫描是没有办法并行执行的,从12.1开始,Oracle可以并行的执行索引扫描。

首先创建测试环境:

SQL> create table t_para_ind (id number, name varchar2(30), created date);

Table created.

SQL> insert into t_para_ind select id, object_name, created from t_big;

6735106 rows created.

SQL> commit;

Commit complete.

SQL> create index ind_para_created on t_para_ind (created);

Index created.

SQL> select banner from v$version;

BANNER

——————————————————————————–

Oracle Database 18c Enterprise Edition Release 18.0.0.0.0 – Production

强制执行计划采用索引扫描:

SQL> select /*+ index(t) */ count(name) from t_para_ind t where created >= to_date(‘201701’, ‘yyyymm’);

Elapsed: 00:00:00.61

————————————————————————————–

| Id | Operation                             | Name              | Rows   | Cost (%CPU)|

————————————————————————————–

| 0 | SELECT STATEMENT                      |                   |      1 | 63096    (1)|

| 1 |   SORT AGGREGATE                       |                   |      1 |             |

| 2 |    TABLE ACCESS BY INDEX ROWIDBATCHED| T_PARA_IND        |   3365K| 63096    (1)|

|* 3 |     INDEX RANGE SCAN                   | IND_PARA_CREATED |   3672K|   9850    (2)|

————————————————————————————–

下面设置语句级并行执行,首先将优化器参数设置为11.2.0.4版本:

SQL> select /*+ index(t) parallel(2) opt_param(‘optimizer_features_enable’, ‘11.2.0.4’) */ count(name) from t_para_ind t where created >= to_date(‘201701’, ‘yyyymm’);

Elapsed: 00:00:00.64

——————————————————————————

| Id | Operation                     | Name              | Rows   | Cost (%CPU)|

——————————————————————————

| 0 | SELECT STATEMENT              |                   |      1 | 63096    (1)|

| 1 |   SORT AGGREGATE               |                   |      1 |             |

| 2 |    TABLE ACCESS BY INDEX ROWID| T_PARA_IND        |   3365K| 63096    (1)|

|* 3 |     INDEX RANGE SCAN           | IND_PARA_CREATED |   3672K|   9850    (2)|

——————————————————————————

对于11.2.0.4的优化器版本,即使设置了并行提示,Oracle也会忽略并行,而采用串行索引范围扫描执行计划。

即使都是索引串行扫描,11.2和12c中还是有一点小差异的。在12c中,Oracle引入了批量ROWID提取的新特性,在执行计划中由关键字BATCHED标识。可以看到11.2和12c中执行效率也有很小的差异,而这个性能提升就是这个批量处理新特性带来的。

Oracle无法采用并行执行的原因是由索引的存储结构决定的,当执行索引访问时,Oracle首先定位到Btree索引的根节点,通过与根节点中存储的键值前缀进行比较,定位到枝叶节点,重复比较的过程,最终定位到叶子节点。在叶子节点上Oracle找到了第一条满足条件的键值,然后Oracle会根据叶节点上的链表扫描下一个叶节点,不断重复这个过程,直到不满足查询限制条件的记录出现。

也就是说Oracle需要根据顺序访问一条链表,只有找到第一个索引块才知道下一个要访问的索引块在哪里,因此这个过程没有办法拆分到多个进程同时执行,这就是为什么索引范围扫描一直无法并行的原因。

Oracle在12c中使得索引扫描可以并行执行,下面看看Oracle是如何实现的:

SQL> select /*+ index(t) parallel(2) */ count(name) from t_para_ind t where created >= to_date(‘201701’, ‘yyyymm’);

Elapsed: 00:00:00.38

—————————————————————————————-

|Id |Operation |Name             |   TQ |IN-OUT|PQ Distrib |

—————————————————————————————-

| 0|SELECT STATEMENT                         |                 |      |       |            |

| 1| SORT AGGREGATE                          |                 |      |       |            |

| 2|   PX COORDINATOR                         |                 |     |       |            |

| 3|    PX SEND QC (RANDOM)                   |:TQ10001         |Q1,01| P->S |QC (RAND)   |

| 4|     SORT AGGREGATE                       |                 |Q1,01| PCWP |            |

| 5|      TABLE ACCESS BY INDEX ROWID BATCHED|T_PARA_IND       |Q1,01| PCWP |            |

| 6|       PX RECEIVE                         |                 |Q1,01| PCWP |            |

| 7|        PX SEND HASH (BLOCK ADDRESS)      |:TQ10000         |Q1,00| S->P |HASH (BLOCK|

| 8|         PX SELECTOR                      |                 |Q1,00| SCWC |            |

|* 9| INDEX RANGE SCAN                |IND_PARA_CREATED|Q1,00| SCWP |            |

—————————————————————————————-

为了输出格式的可读性,把执行计划中和当前关系不大的列去掉了。

可以看到Oracle确实采用了并行的执行计划,而且执行时间也比串行执行快。

如果仔细观察IN-OUT列,就会发现Oracle的并行执行实际上从第6步才开始,第7步是串行到并行的过程,而第7步之前的第9步和第8步都是串行执行。

也就是说Oracle把索引范围扫描的过程分成了两部分,一部分是之前讨论的索引范围扫描部分,而另一部分是索引扫描后根据rowid的读取表中记录的过程。对于前者,即使是在12c中,Oracle仍然采用串行的扫描方式执行,而对于后者,Oracle将其并行化。这也是性能提升的由来。

SQL> select /*+ index(t) parallel(4) */ count(name) from t_para_ind t where created >= to_date(‘201701’, ‘yyyymm’);

Elapsed: 00:00:00.56

—————————————————————————————-

|Id |Operation |Name             |   TQ |IN-OUT|PQ Distrib |

—————————————————————————————-

| 0|SELECT STATEMENT                         |                 |      |       |            |

| 1| SORT AGGREGATE                          |                |      |       |            |

| 2|   PX COORDINATOR                         |                 |      |       |            |

| 3|    PX SEND QC (RANDOM)                   |:TQ10001         |Q1,01| P->S |QC (RAND)   |

| 4|     SORT AGGREGATE                      |                 |Q1,01| PCWP |            |

| 5|      TABLE ACCESS BY INDEX ROWID BATCHED|T_PARA_IND       |Q1,01| PCWP |            |

| 6|       PX RECEIVE                         |                 |Q1,01| PCWP |            |

| 7|        PX SEND HASH (BLOCK ADDRESS)      |:TQ10000         |Q1,00| S->P |HASH (BLOCK|

| 8|         PX SELECTOR                      |                 |Q1,00| SCWC |           |

|* 9| INDEX RANGE SCAN                |IND_PARA_CREATED|Q1,00| SCWP |            |

—————————————————————————————-

但是这种方式的分拆并不是真正意义的并行,因为其中的一部分是无法并行的,所以当我们进一步加大并行度的时候,执行时间反而变长了。

SQL> select /*+ index(t) parallel(4) */ count(*) from t_para_ind t where created >= to_date(‘201701’, ‘yyyymm’);

Elapsed: 00:00:00.17

——————————————————————-

| Id | Operation          | Name              | Rows   | Cost (%CPU)|

——————————————————————-

| 0 | SELECT STATEMENT   |                   |      1 |   9850    (2)|

| 1 |   SORT AGGREGATE    |                   |      1 |             |

|* 2 |    INDEX RANGE SCAN| IND_PARA_CREATED |   3365K|   9850    (2)|

——————————————————————-

而如果我们修改 SQL 语句,把原本的COUNT(NAME)改为COUNT(*),这时由于执行计划中回表部分不再需要,执行计划只剩下不能并行的索引扫描部分,因此执行计划又恢复了串行执行。这又一次证实了12c的并行索引扫描只是部分并行,其提升总体扫描效率的能力是有限的。

下面看看全表扫描的并行执行:

SQL> select count(name) from t_para_ind t where created >= to_date(‘201701’, ‘yyyymm’);

Elapsed: 00:00:00.24

————————————————————–

| Id | Operation           | Name        | Rows   | Cost (%CPU)|

————————————————————–

| 0 | SELECT STATEMENT    |             |      1 | 11519    (2)|

| 1 |   SORT AGGREGATE     |             |      1 |             |

|* 2 |    TABLE ACCESS FULL| T_PARA_IND |   3073K| 11519    (2)|

————————————————————–

串行全表扫描时,执行时间为0.24秒。

SQL> select /*+ parallel(2) */ count(name) from t_para_ind t where created >= to_date(‘201701’, ‘yyyymm’);

Elapsed: 00:00:00.15

————————————————————————–

| Id | Operation               | Name        |     TQ   |IN-OUT| PQ Distrib |

————————————————————————–

| 0 | SELECT STATEMENT        |             |         |       |             |

| 1 |   SORT AGGREGATE         |             |         |       |             |

| 2 |    PX COORDINATOR        |             |         |       |             |

| 3 |     PX SEND QC (RANDOM) | :TQ10000    |   Q1,00 | P->S | QC (RAND)   |

| 4 |      SORT AGGREGATE      |             |   Q1,00 | PCWP |             |

| 5 |       PX BLOCK ITERATOR |             |   Q1,00 | PCWC |             |

|* 6 |        TABLE ACCESS FULL| T_PARA_IND |   Q1,00 | PCWP |             |

————————————————————————–

开启2路并行时,执行时间为0.15秒。

SQL> select /*+ parallel(4) */ count(name) from t_para_ind t where created >= to_date(‘201701’, ‘yyyymm’);

Elapsed: 00:00:00.08

————————————————————————–

| Id | Operation               | Name        |     TQ   |IN-OUT| PQ Distrib |

————————————————————————–

| 0 | SELECT STATEMENT        |             |         |       |             |

| 1 |   SORT AGGREGATE         |             |         |       |             |

| 2 |    PX COORDINATOR        |             |         |       |             |

| 3 |     PX SEND QC (RANDOM) | :TQ10000    |   Q1,00 | P->S | QC (RAND)   |

| 4 |      SORT AGGREGATE      |             |   Q1,00 | PCWP |             |

| 5 |       PX BLOCK ITERATOR |             |   Q1,00 | PCWC |             |

|* 6 |        TABLE ACCESS FULL| T_PARA_IND |   Q1,00 | PCWP |             |

————————————————————————–

开启4路并行时,执行时间降低到了0.08秒。显然全表扫描才是真正的并行,在合理的数据量和资源消耗范围内,其执行时间是随着并行度增大而等比降低的。


以上所述就是小编给大家介绍的《12c新增并行索引扫描》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java Message Service API Tutorial and Reference

Java Message Service API Tutorial and Reference

Hapner, Mark; Burridge, Rich; Sharma, Rahul / 2002-2 / $ 56.49

Java Message Service (JMS) represents a powerful solution for communicating between Java enterprise applications, software components, and legacy systems. In this authoritative tutorial and comprehens......一起来看看 《Java Message Service API Tutorial and Reference》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具