oracle执行计划走索引的方式,执行计划中常见index访问方式 – 提供7*24专业数据库(Oracle,SQL Server,MySQL等)恢复和Oracle技术服务@Tel:+86 13429...

近期有朋友对于单个表上的index各种情况比较模糊,这里对于单个表上,单个index出现的大多数情况进行了总结性测试,给出了测试结果,至于为什么出现这样的试验结果未做过多解释,给读者留下思考的空间.本篇文章仅仅是为了测试hint对index的影响,而不是说明走各种index方式的好坏.参考: INDEX FULL SCAN vs INDEX FAST FULL SCAN

创建表模拟测试

SQL> create table t_xifenfei as select object_id,object_name from dba_objects;

Table created.

SQL> create index i_t_object_id on t_xifenfei(object_id);

Index created.

SQL> exec dbms_stats.gather_table_stats(USER,'T_XIFENFEI',cascade=>true);

PL/SQL procedure successfully completed.

SQL> desc t_xifenfei

Name Null? Type

----------------------------------------- -------- ----------------------------

OBJECT_ID NUMBER

OBJECT_NAME VARCHAR2(128)

TABLE ACCESS FULL

SQL> SET AUTOT TRACE EXP STAT

SQL> SELECT OBJECT_ID FROM T_XIFENFEI;

49838 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 548923532

--------------------------------------------------------------------------------

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

--------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 49838 | 243K| 57 (2)| 00:00:01 |

| 1 | TABLE ACCESS FULL| T_XIFENFEI | 49838 | 243K| 57 (2)| 00:00:01 |

--------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

3544 consistent gets

0 physical reads

0 redo size

721203 bytes sent via SQL*Net to client

36927 bytes received via SQL*Net from client

3324 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

49838 rows processed

SQL> SELECT /*+ INDEX(T i_t_object_id) */ OBJECT_ID FROM T_XIFENFEI;

49838 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 548923532

--------------------------------------------------------------------------------

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

--------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 49838 | 243K| 57 (2)| 00:00:01 |

| 1 | TABLE ACCESS FULL| T_XIFENFEI | 49838 | 243K| 57 (2)| 00:00:01 |

--------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

3544 consistent gets

0 physical reads

0 redo size

721203 bytes sent via SQL*Net to client

36927 bytes received via SQL*Net from client

3324 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

49838 rows processed

从上面的执行计划中可知,此时走了全表扫描. 由于我们需要查询的列为object_id,因此理论上只需要读取索引就应该可以返回所有数据,而此时为什么是全表扫描呢? 这是因为NULL值与索引的特性所决定的.即null值不会被存储到B树索引.因此应该为表 t_xifenfei 的列 object_id 添加 not null 约束.

INDEX FAST FULL SCAN

SQL> alter table t_xifenfei modify(object_id not null);

Table altered.

SQL> SELECT object_id from t_xifenfei;

49838 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 2036340805

--------------------------------------------------------------------------------------

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

--------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 49838 | 243K| 27 (4)| 00:00:01 |

| 1 | INDEX FAST FULL SCAN| I_T_OBJECT_ID | 49838 | 243K| 27 (4)| 00:00:01 |

--------------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

3432 consistent gets

0 physical reads

0 redo size

721203 bytes sent via SQL*Net to client

36927 bytes received via SQL*Net from client

3324 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

49838 rows processed

INDEX FAST FULL SCAN:当在高速缓存中没有找到所需的索引块时,则根据db_file_multiblock_read_count的值进行多块读操作.对于索引的分支结构只是简单的获取,然后扫描所有的叶结点.其结果是导致索引结构没有访问,获取的数据没有根据索引键的顺序排序.INDEX FAST FULL SCAN使用multiblock_read,故产生db file scattered reads 事件.

INDEX RANGE SCAN

SQL> select object_id from t_xifenfei where object_id<10;

8 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 2197008162

----------------------------------------------------------------------------------

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

----------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 2 | 10 | 2 (0)| 00:00:01 |

|* 1 | INDEX RANGE SCAN| I_T_OBJECT_ID | 2 | 10 | 2 (0)| 00:00:01 |

----------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - access("OBJECT_ID"<10)

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

3 consistent gets

0 physical reads

0 redo size

499 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

8 rows processed

SQL> select /*+ index_ffs(t i_t_object_id) */ object_id from t_xifenfei t where object_id<10;

8 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 2036340805

--------------------------------------------------------------------------------------

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

--------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 2 | 10 | 27 (4)| 00:00:01 |

|* 1 | INDEX FAST FULL SCAN| I_T_OBJECT_ID | 2 | 10 | 27 (4)| 00:00:01 |

--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):

---------------------------------------------------

1 - filter("OBJECT_ID"<10)

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

118 consistent gets

0 physical reads

0 redo size

499 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

8 rows processed

1

这里可以看出index_ffs已经生效,但是对于这样的情况hint index_ffs效率一般来说不会太高.

INDEX FULL SCAN

1

SQL> SELECT /*+ INDEX(T i_t_object_id) */ object_id from t_xifenfei t;

49838 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 431110666

----------------------------------------------------------------------------------

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

----------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 49838 | 243K| 113 (2)| 00:00:02 |

| 1 | INDEX FULL SCAN | I_T_OBJECT_ID | 49838 | 243K| 113 (2)| 00:00:02 |

----------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

3426 consistent gets

0 physical reads

0 redo size

721203 bytes sent via SQL*Net to client

36927 bytes received via SQL*Net from client

3324 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

49838 rows processed

INDEX FULL SCAN:完全按照索引存储的顺序依次访问整个索引树.当访问到叶结点之后,按照双向链表方式读取相连节点的值.换言之,对于索引上所有的数据是按照有序的方式来读取的.如果索引块没有在高速缓存中被找到时,则需要从数据文件中单块进行读取.对于需要读取大量数据的全索引扫描而言,这将使其变得低效.INDEX FULL SCAN使用single read,故产生db file sequential reads事件.新版的Oracle支持db file parallel reads方式.

HINT INDEX不会使用INDEX FAST FULL SCAN功能.

INDEX列ORDER BY

SQL> SELECT OBJECT_ID FROM T_XIFENFEI order by object_id ;

49838 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 431110666

----------------------------------------------------------------------------------

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

----------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 49838 | 243K| 113 (2)| 00:00:02 |

| 1 | INDEX FULL SCAN | I_T_OBJECT_ID | 49838 | 243K| 113 (2)| 00:00:02 |

----------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

3426 consistent gets

0 physical reads

0 redo size

721203 bytes sent via SQL*Net to client

36927 bytes received via SQL*Net from client

3324 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

49838 rows processed

SQL> SELECT OBJECT_ID FROM T_XIFENFEI order by object_id desc;

49838 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 2808014233

--------------------------------------------------------------------------------------------

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

--------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 49838 | 243K| 113 (2)| 00:00:02 |

| 1 | INDEX FULL SCAN DESCENDING| I_T_OBJECT_ID | 49838 | 243K| 113 (2)| 00:00:02 |

--------------------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

3427 consistent gets

0 physical reads

0 redo size

721203 bytes sent via SQL*Net to client

36927 bytes received via SQL*Net from client

3324 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

49838 rows processed

SQL> SELECT /*+ index_ffs(t i_t_object_id) */ object_id from t_xifenfei t order by object_id;

49838 rows selected.

Execution Plan

----------------------------------------------------------

Plan hash value: 2527678987

-----------------------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |

-----------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 49838 | 243K| | 185 (4)| 00:00:03 |

| 1 | SORT ORDER BY | | 49838 | 243K| 1192K| 185 (4)| 00:00:03 |

| 2 | INDEX FAST FULL SCAN| I_T_OBJECT_ID | 49838 | 243K| | 27 (4)| 00:00:01 |

-----------------------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

117 consistent gets

0 physical reads

0 redo size

721203 bytes sent via SQL*Net to client

36927 bytes received via SQL*Net from client

3324 SQL*Net roundtrips to/from client

1 sorts (memory)

0 sorts (disk)

49838 rows processed

对于index 列排序,默认情况下会使用INDEX FULL SCAN/INDEX FULL SCAN DESCENDING而不选择使用INDEX FAST FULL SCAN,因为INDEX FAST FULL SCAN获得数据后,还需要做一次SORT ORDER BY操作

INDEX FAST FULL SCAN+SORT AGGREGATE

SQL> SELECT count(object_id) FROM T_XIFENFEI;

Execution Plan

----------------------------------------------------------

Plan hash value: 3095383276

-------------------------------------------------------------------------------

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

-------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 27 (4)| 00:00:01 |

| 1 | SORT AGGREGATE | | 1 | | |

| 2 | INDEX FAST FULL SCAN| I_T_OBJECT_ID | 49838 | 27 (4)| 00:00:01 |

-------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

117 consistent gets

0 physical reads

0 redo size

421 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

SQL> SELECT /*+ INDEX(T i_t_object_id) */ count(object_id) FROM T_XIFENFEI t;

Execution Plan

----------------------------------------------------------

Plan hash value: 3079973526

--------------------------------------------------------------------------

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

--------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 113 (2)| 00:00:02 |

| 1 | SORT AGGREGATE | | 1 | | |

| 2 | INDEX FULL SCAN| I_T_OBJECT_ID | 49838 | 113 (2)| 00:00:02 |

--------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

111 consistent gets

0 physical reads

0 redo size

421 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

sort aggregate通常发生在使用一些聚合函数的时候,sum(),avg(),min(),max(),count()等等,实际上sort aggregate不做真正的sort,并不会用到排序空间,而是通过一个全局变量+全表或全索引扫描来实现.这样的操作在默认情况下使用INDEX FAST FULL SCAN

INDEX FULL SCAN (MIN/MAX)

SQL> SELECT max(object_id) FROM T_XIFENFEI;

Execution Plan

----------------------------------------------------------

Plan hash value: 2939893782

--------------------------------------------------------------------------------------------

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

--------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 5 | 2 (0)| 00:00:01 |

| 1 | SORT AGGREGATE | | 1 | 5 | | |

| 2 | INDEX FULL SCAN (MIN/MAX)| I_T_OBJECT_ID | 49838 | 243K| 2 (0)| 00:00:01 |

--------------------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

2 consistent gets

0 physical reads

0 redo size

419 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

SQL> SELECT /*+ index_ffs(t i_t_object_id) */ max(object_id) FROM T_XIFENFEI t;

Execution Plan

----------------------------------------------------------

Plan hash value: 2939893782

--------------------------------------------------------------------------------------------

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

--------------------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | 1 | 5 | 27 (4)| 00:00:01 |

| 1 | SORT AGGREGATE | | 1 | 5 | | |

| 2 | INDEX FULL SCAN (MIN/MAX)| I_T_OBJECT_ID | 49838 | 243K| 27 (4)| 00:00:01 |

--------------------------------------------------------------------------------------------

Statistics

----------------------------------------------------------

1 recursive calls

0 db block gets

2 consistent gets

0 physical reads

0 redo size

419 bytes sent via SQL*Net to client

385 bytes received via SQL*Net from client

2 SQL*Net roundtrips to/from client

0 sorts (memory)

0 sorts (disk)

1 rows processed

对于这样的查询INDEX FULL SCAN (MIN/MAX)明显是最优,但是此处奇怪的是使用了index_ffs提示无效,如果有知道的朋友,麻烦告知原因.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值