您的位置:首页 > 数据库 > Oracle

oracle CBO优化器何时会选择全表扫描

2013-11-02 19:16 741 查看
全表扫描将读取高水位线(HWM)之下的所有数据块从数据文件读到缓冲区,然后读取每项行数据,看是否满足WHERE子句过滤条件。
当Oracle执行全表扫描时会按顺序读取每个块且只读一次,如果能够一次读取多个块,可以有效的提高效率,
初始化参数DB_FILE_MULTIBLOCK_READ_COUNT用来设置在一次I/O中可以读取多少个数据块。

通常我们认为应该避免全表扫描,但是在检索大量数据时全表扫描优于索引扫描,这正是因为全表扫描可以在一次I/O中读却多个块,从而减少了I/O的次数。在使用全表扫描的同时也可以使用并行来提高扫描的速度。

CBO优化器何时会选择全表扫描:
1) 无合适的索引。

2) 检索表中绝大多数的数据。  

3) 表非常小。

SQL> create table d as select * from scott.emp where deptno=10;

SQL> select * from d;

EMPNO ENAME      JOB         MGR HIREDATE          SAL      COMM DEPTNO

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

 7782 CLARK      MANAGER    7839 1981/6/9      2450.00               10

 7839 KING       PRESIDENT       1981/11/17    5000.00               10

 7934 MILLER     CLERK      7782 1982/1/23     1300.00               10

SQL>create index empno_index on d (empno);

SQL>select * from d where empno=7782;  

Execution Plan

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

Plan hash value: 3387653791

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

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

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

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

|*  1 |  TABLE ACCESS FULL| D    |     1 |    87 |     2   (0)| 00:00:01 |

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

Predicate Information (identified by operation id):

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

   1 - filter("EMPNO"=7782)

Note

-----

   - dynamic sampling used for this statement (level=2)

Statistics

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

          9  recursive calls

          0  db block gets

         10  consistent gets

          0  physical reads

          0  redo size

        864  bytes sent via SQL*Net to client

        419  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

因为表中的块小于参数DB_FILE_MULTIBLOCK_READ_COUNT设置的值,只需一次I/O

4) 高并行度。             

如果在表级设置了较高的并行度,通常会使CBO选择全表扫描。

通常建议在语句级用HINTS来实现并行,如/*+full(table_name) parallel(table_name degree)*/。

5) 太旧的统计数据。如果表没有进行过分析或很久没有再次分析,CBO可能会错误的认为表含有及少的数据块。-------必要时对表手动做统计信息

6) 在语句中嵌入了全表扫描的HINTS。  -----指定表的执行计划路径
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: