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新增并行索引扫描》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

四步创业法

四步创业法

[美] Steven Gary Blank / 七印部落 / 华中科技大学出版社 / 2012-8-1 / 48.00

《四步创业法》获李开复推荐,是精益创业理论的奠基之作。作者Steven Gary Blank博士是硅谷资深企业家,他一共创办了八家企业,并担任多家硅谷公司的董事和创业顾问。本书总结作者25年创业经验,提出全新的客户发展方法 (诣在弥补传统产品开发方法的缺陷) ,掀起了硅谷近年精益创业 的浪潮。七印部落正在翻译作者的博客和授课视频,欢迎访问微博:http://weibo.com/7seals ......一起来看看 《四步创业法》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

在线进制转换器
在线进制转换器

各进制数互转换器

SHA 加密
SHA 加密

SHA 加密工具