优化器在形成执行计划时需要做的一个重要选择——如何从数据库查询出需要的数据。对于SQL语句存取的任何表中的任何行,可能存在许多存取路径(存取方法),通过它们可以定位和查询出需要的数据。优化器选择其中自认为是最优化的路径。

在物理层,Oracle读取数据,一次读取的最小单位为数据库块(由多个连续的操作系统块组成),一次读取的最大值由操作系统一次I/O的最大值与multiblock参数共同决定,所以即使只需要一行数据,也是将该行所在的数据库块读入内存。逻辑上,Oracle用如下存取方法访问数据:

Oracle全表扫描(Full Table Scans, FTS)

为实现Oracle全表扫描,Oracle读取表中所有的行,并检查每一行是否满足语句的WHERE限制条件。Oracle顺序地读取分配给表的每个数据块,直到读到表的最高水线处(high water mark, HWM,标识表的最后一个数据块)。一个多块读操作可以使一次I/O能读取多块数据块(db_block_multiblock_read_count参数设定),而不是只读取一个数据块,这极大的减少了I/O总次数,提高了系统的吞吐量,所以利用多块读的方法可以十分高效地实现Oracle全表扫描,而且只有在Oracle全表扫描的情况下才能使用多块读操作。在这种访问模式下,每个数据块只被读一次。由于HWM标识最后一块被读入的数据,而delete操作不影响HWM值,所以一个表的所有数据被delete后,其Oracle全表扫描的时间不会有改善,一般我们需要使用truncate命令来使HWM值归为0。幸运的是Oracle 10G后,可以人工收缩HWM的值。

由FTS模式读入的数据被放到高速缓存的Least Recently Used (LRU)列表的尾部,这样可以使其快速交换出内存,从而不使内存重要的数据被交换出内存。

使用FTS的前提条件:在较大的表上不建议使用Oracle全表扫描,除非取出数据的比较多,超过总量的5% -- 10%,或你想使用并行查询功能时。

使用Oracle全表扫描的例子:

SQL> set autotrace traceonly;
SQL> select * from dept where dname <> 'SALES';

执行计划
----------------------------------------------------------
Plan hash value: 3383998547

--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      |     3 |    60 |     3   (0)| 00:00:01 |
|*  1 |  TABLE ACCESS FULL| DEPT |     3 |    60 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------

SQL> select * from dept;

DEPTNO DNAME          LOC
---------- -------------- ---------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON

可以查出dept表的数据块信息如下:
SQL>  select  dbms_rowid.rowid_object(rowid) objectid
  2             ,dbms_rowid.rowid_relative_fno(rowid) fileid
  3             ,dbms_rowid.rowid_block_number(rowid) blockid
  4             ,dbms_rowid.rowid_row_number(rowid) rownums
  5             ,deptno
  6      from dept;

OBJECTID     FILEID    BLOCKID    ROWNUMS     DEPTNO
---------- ---------- ---------- ---------- ----------
     51149          4         16          0         10
     51149          4         16          1         20
     51149          4         16          2         30
     51149          4         16          3         40

分析:此例中Oracle读取dept表中的所有行(即读取BLOCKID=16的数据块,一次性读入了此数据块上的4条记录),选出满足条件的3条记录(dname='ACCOUNTING', 'RESEARCH', 'OPERATIONS')。

行的ROWID指出了该行所在的数据文件、数据块以及行在该块中的位置,所以通过ROWID来存取数据可以快速定位到目标数据上,是Oracle存取单行数据的最快方法。为了通过ROWID存取表,Oracle 首先要获取被选择行的ROWID,或者从语句的WHERE子句中得到,或者通过表的一个或多个索引的索引扫描得到。Oracle然后以得到的ROWID为依据定位每个被选择的行。这种存取方法不会用到多块读操作,一次I/O只能读取一个数据块。我们会经常在执行计划中看到该存取方法,如通过索引查询数据。

使用ROWID存取的方法:

SQL> select * from dept where rowid='AAAMfNAAEAAAAAQAAA';

执行计划
----------------------------------------------------------
Plan hash value: 3453257278

-----------------------------------------------------------------------------------
| Id  | Operation                  | Name | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT           |      |     1 |    20 |     1   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY USER ROWID| DEPT |     1 |    20 |     1   (0)| 00:00:01 |
-----------------------------------------------------------------------------------

Oracle全表扫描的更多相关文章

  1. Oracle列操作引起的全表扫描

    首先是一种比较明显的情况: select * from table where column + 1 = 2 这里对column进行了列操作,加1以后,与column索引里的内容对不上,导致colum ...

  2. Oracle 表的访问方式(1) ---全表扫描、通过ROWID访问表

    1.Oracle访问表的方式 全表扫描.通过ROWID访问表.索引扫描 2.全表扫描(Full Table Scans, FTS) 为实现全表扫描,Oracle顺序地访问表中每条记录,并检查每一条记录 ...

  3. Oracle 高水位线和全表扫描

    --Oracle 高水位线和全表扫描--------------------------2013/11/22 高水位线好比水库中储水的水位线,用于描述数据库中段的扩展方式.高水位线对全表扫描方式有着至 ...

  4. Oracle 11g全表扫描以Direct Path Read方式执行

    在Oracle Database 11g中有一个新特性,全表扫描可以通过直接路径读的方式来执行(Direct Path Read),这是一个合理的变化,如果全表扫描的大量数据读取是偶发性的,则直接路径 ...

  5. Oracle的大表,小表与全表扫描

    大小表区分按照数据量的大小区分: 通常对于小表,Oracle建议通过全表扫描进行数据访问,对于大表则应该通过索引以加快数据查询,当然如果查询要求返回表中大部分或者全部数据,那么全表扫描可能仍然是最好的 ...

  6. Oracle收集对表收集统计信息导致全表扫描直接路径读?

    direct path read深入解析 前言 最近碰到一件很奇葩的事情,因为某条SQL执行缓慢,原因是走了笛卡尔(两组大数据结果集),而且笛卡尔还是NL的一个部分,要循环31M次. 很容易发现是统计 ...

  7. oracle优化:避免全表扫描(高水位线)

    如果我们查询了一条SQL语句,这条SQL语句进行了全表扫描,那到底是扫描了多少个数据块呢?是表有多少数据,就扫描多少块吗?不是的.而是扫描高水位线一下的所有块.有的时候有人经常说,我的表也不大呀,怎么 ...

  8. (转) Oracle SQL优化必要的全表扫描思路分析

    大多数情况下,我们需要避免SQL在查询时进行全表扫描(FTS),但是对于必须需要进行全表扫描的情况,也可以进行一些优化处理. 即使全表扫描是检索所需数据的唯一可行方法,仍然有多种方法来提升查询性能.优 ...

  9. 想通过加HINT让其走全表扫描

    一个SQL,通过SPM固定它的执行计划,可以通过DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE实现.也可以通地此功能在不修改原SQL的情况下对其加HINT来固定执行计划.D ...

随机推荐

  1. 无法挂载 “7.9 GB Filesystem”.

    有个8G的U盘,格式化成exfat格式.插入电脑后点击盘符,弹出错误提示: 无法挂载 “7.9 GB Filesystem”. Error mounting: mount exited with ex ...

  2. ubuntu14_gtk 安装

    1:apt-get install build-essential2:apt-get install gnome-devel gnome-devel-docs

  3. 【组合数的唯一分解定理】Uva1635

    给出n.m,求得最终求和数列an=C(n-1,0)*x1 + C(n-1,1)*x2+...+C(n-1,n-1)*xn; 若xi与m无关,则an除以m的余数与xi无关,即余数不含xi的项: 输入:n ...

  4. poj 3565 二分图最优匹配

    思路: 将ant与tree之间用距离来做权值,求最小权匹配就可以了.可以想到,如果有两条线段相交,那么将这两个线段交换一个顶点,使其不相交,其权值和一定会更小. 就像斜边永远比直角边长一样的道理. # ...

  5. Java Servlet-http协议

    ---恢复内容开始--- 互联网三大基石: url:定位数据 html:显示数据 http:传输数据

  6. 打造属于自己的安卓Metro界面

    前言: 各位小伙伴,又到了每周更新文章了时候了,本来是周日能发出来呢,这不是赶上清明节吗,女王大人发话了,清明节前两天半陪她玩,只留给我周一下午半天时间写博客,哪里有女王哪里就有压迫呀有木有!好了闲话 ...

  7. 浏览器userAgent大全

    iPhone ●iOSMozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Versi ...

  8. Xcode7打包上传App Store发生ERROR ITMS-90535 错误解决方法

    两个方法解决  1.如果用不到QQ分享啥的,直接删掉TencentOpenApi这个文件夹. 移除掉这个模块 ..简单粗暴,我就是这么解决的. 2.找到TencentOpenApi_IOS_Bundl ...

  9. CSS选择器介绍

    一.元素选择器 E{...} 二.属性选择器 E[attr]{...}:指定该CSS对具有attr的元素起作用: E[attr=value]{...}::指定该CSS对具有attr的值为value的元 ...

  10. 学习之spring自带缓存

    <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://w ...