欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

index full scan 和index fast full scan

程序员文章站 2022-06-02 13:02:27
...

RDBMS 12.2.0.1 

参考文档:

Optimizer Access Paths (oracle.com)

根据官方文档,简单总结下:

index full scan和index fast full scan的主要区别,是读取索引的记录是否有序。
index full scan  -- 读取索引,有序 ,使用单块IO读取索引 (单块读IO效率较高)
index fast full scan  -- 读取索引,无序 ,使用多块IO读取索引 


-- 以下为官方文档的说明

8.3.4 Index Full Scans

An index full scan reads the entire index in order. An index full scan can eliminate a separate sorting operation because the data in the index is ordered by index key.

This section contains the following topics:

8.3.4.1 When the Optimizer Considers Index Full Scans

The optimizer considers an index full scan in a variety of situations.

The situations include the following:

  • A predicate references a column in the index. This column need not be the leading column.

  • No predicate is specified, but all of the following conditions are met:

    • All columns in the table and in the query are in the index.

    • At least one indexed column is not null.

  • A query includes an ORDER BY on indexed non-nullable columns.

8.3.4.2 How Index Full Scans Work

The database reads the root block, and then navigates down the left hand side of the index (or right if doing a descending full scan) until it reaches a leaf block.

Then the database reaches a leaf block, the scan proceeds across the bottom of the index, one block at a time, in sorted order. The database uses single-block I/O rather than multiblock I/O.

The following graphic illustrates an index full scan. A statement requests the departments records ordered by department_id.

8.3.5 Index Fast Full Scans

An index fast full scan reads the index blocks in unsorted order, as they exist on disk. This scan does not use the index to probe the table, but reads the index instead of the table, essentially using the index itself as a table.

This section contains the following topics:

8.3.5.1 When the Optimizer Considers Index Fast Full Scans

The optimizer considers this scan when a query only accesses attributes in the index.

Note:

Unlike a full scan, a fast full scan cannot eliminate a sort operation because it does not read the index in order.

The INDEX_FFS(table_name index_name) hint forces a fast full index scan.

See Also:

Oracle Database SQL Language Reference to learn more about the INDEX hint

8.3.5.2 How Index Fast Full Scans Work

The database uses multiblock I/O to read the root block and all of the leaf and branch blocks. The databases ignores the branch and root blocks and reads the index entries on the leaf blocks.

-- 以下为测试

-- index full scan 

[email protected]> set autotrace traceonly
[email protected]> SELECT department_id, department_name
  2  FROM   departments
  3  ORDER BY department_id;

27 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 3145200496

-------------------------------------------------------------------------------------------
| Id  | Operation                   | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |             |    27 |   432 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| DEPARTMENTS |    27 |   432 |     2   (0)| 00:00:01 |
|   2 |   INDEX FULL SCAN           | DEPT_ID_PK  |    27 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------


Statistics
----------------------------------------------------------
         50  recursive calls
          0  db block gets
        112  consistent gets
          2  physical reads
          0  redo size
       1358  bytes sent via SQL*Net to client
        618  bytes received via SQL*Net from client
          3  SQL*Net roundtrips to/from client
          6  sorts (memory)
          0  sorts (disk)
         27  rows processed

[email protected]> 

-- index fast full scan

-- 不加hint 提示,使用的是 index full scan 

[email protected]> SELECT   COUNT(*) FROM   departments;


Execution Plan
----------------------------------------------------------
Plan hash value: 373888742

-----------------------------------------------------------------------
| Id  | Operation        | Name       | Rows  | Cost (%CPU)| Time     |
-----------------------------------------------------------------------
|   0 | SELECT STATEMENT |            |     1 |     1   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE  |            |     1 |            |          |
|   2 |   INDEX FULL SCAN| DEPT_ID_PK |    27 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          1  consistent gets
          0  physical reads
          0  redo size
        542  bytes sent via SQL*Net to client
        607  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

-- 加上hint提示,走index fast full scan

[email protected]> SELECT /*+ INDEX_FFS(departments dept_id_pk) */ COUNT(*) FROM   departments;


Execution Plan
----------------------------------------------------------
Plan hash value: 2315979460

----------------------------------------------------------------------------
| Id  | Operation             | Name       | Rows  | Cost (%CPU)| Time     |
----------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |            |     1 |     2   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE       |            |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| DEPT_ID_PK |    27 |     2   (0)| 00:00:01 |
----------------------------------------------------------------------------


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          4  consistent gets
          1  physical reads
          0  redo size
        542  bytes sent via SQL*Net to client
        607  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

[email protected]> 		  

-- 再次使用两个语句,验证两种扫描方式的效率 ,可以看到 index full scan 效率较高 (一致读,物理读等等的比较)

SELECT /*+ INDEX_FFS(e emp_name_ix) */ first_name   FROM employees e;

SELECT  first_name   FROM employees e;
[email protected]> SELECT /*+ INDEX_FFS(e emp_name_ix) */ first_name   FROM employees e;

107 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1847877723

------------------------------------------------------------------------------------
| Id  | Operation            | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT     |             |   107 |   749 |     2   (0)| 00:00:01 |
|   1 |  INDEX FAST FULL SCAN| EMP_NAME_IX |   107 |   749 |     2   (0)| 00:00:01 |
------------------------------------------------------------------------------------


Statistics
----------------------------------------------------------
        129  recursive calls
          0  db block gets
        202  consistent gets
          2  physical reads
          0  redo size
       2842  bytes sent via SQL*Net to client
        684  bytes received via SQL*Net from client
          9  SQL*Net roundtrips to/from client
          6  sorts (memory)
          0  sorts (disk)
        107  rows processed
[email protected]> SELECT  first_name   FROM employees e;

107 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 2228653197

--------------------------------------------------------------------------------
| Id  | Operation        | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------
|   0 | SELECT STATEMENT |             |   107 |   749 |     1   (0)| 00:00:01 |
|   1 |  INDEX FULL SCAN | EMP_NAME_IX |   107 |   749 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
          9  consistent gets
          0  physical reads
          0  redo size
       2842  bytes sent via SQL*Net to client
        684  bytes received via SQL*Net from client
          9  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
        107  rows processed

[email protected]> 

END