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。 -----指定表的执行计划路径
当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。 -----指定表的执行计划路径
相关文章推荐
- Oracle 设置在全表扫描时跳过损坏的数据块
- oracle优化:避免全表扫描
- Oracle列操作引起的全表扫描
- Oracle 全表扫描和聚簇因子
- Oracle 11g全表扫描以Direct Path Read方式执行
- oracle优化之count的优化-避免全表扫描
- oracle优化:避免全表扫描
- Oracle 全表扫描及其执行计划(full table scan)
- Oracle 11g通过提高IO吞吐量(修改_db_file_optimizer_read_count)来优化全表扫描
- Oracle 索引 避免全表扫描
- oracle优化:避免全表扫描
- 实验:找到优化器选择全表扫描和索引范围扫描的临界点
- 2013.11.1全表扫描 flush"oracle的缓存 SQL递归语句
- oracle是如何进行全表扫描实验
- oracle 性能优化操作十八: 决定使用全表扫描还是使用索引
- Oracle优化:避免全表扫描
- 【转自Oracle ACE-盖国强】Oracle 11g全表扫描以Direct Path Read方式执行
- Oracle全表扫描
- Oracle查找全表扫描的SQL语句
- oracle 11.2.0.3全表扫描COST计算(工作量模式)