Oracle全表扫描
优化器在形成执行计划时需要做的一个重要选择——如何从数据库查询出需要的数据。对于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全表扫描的更多相关文章
- Oracle列操作引起的全表扫描
首先是一种比较明显的情况: select * from table where column + 1 = 2 这里对column进行了列操作,加1以后,与column索引里的内容对不上,导致colum ...
- Oracle 表的访问方式(1) ---全表扫描、通过ROWID访问表
1.Oracle访问表的方式 全表扫描.通过ROWID访问表.索引扫描 2.全表扫描(Full Table Scans, FTS) 为实现全表扫描,Oracle顺序地访问表中每条记录,并检查每一条记录 ...
- Oracle 高水位线和全表扫描
--Oracle 高水位线和全表扫描--------------------------2013/11/22 高水位线好比水库中储水的水位线,用于描述数据库中段的扩展方式.高水位线对全表扫描方式有着至 ...
- Oracle 11g全表扫描以Direct Path Read方式执行
在Oracle Database 11g中有一个新特性,全表扫描可以通过直接路径读的方式来执行(Direct Path Read),这是一个合理的变化,如果全表扫描的大量数据读取是偶发性的,则直接路径 ...
- Oracle的大表,小表与全表扫描
大小表区分按照数据量的大小区分: 通常对于小表,Oracle建议通过全表扫描进行数据访问,对于大表则应该通过索引以加快数据查询,当然如果查询要求返回表中大部分或者全部数据,那么全表扫描可能仍然是最好的 ...
- Oracle收集对表收集统计信息导致全表扫描直接路径读?
direct path read深入解析 前言 最近碰到一件很奇葩的事情,因为某条SQL执行缓慢,原因是走了笛卡尔(两组大数据结果集),而且笛卡尔还是NL的一个部分,要循环31M次. 很容易发现是统计 ...
- oracle优化:避免全表扫描(高水位线)
如果我们查询了一条SQL语句,这条SQL语句进行了全表扫描,那到底是扫描了多少个数据块呢?是表有多少数据,就扫描多少块吗?不是的.而是扫描高水位线一下的所有块.有的时候有人经常说,我的表也不大呀,怎么 ...
- (转) Oracle SQL优化必要的全表扫描思路分析
大多数情况下,我们需要避免SQL在查询时进行全表扫描(FTS),但是对于必须需要进行全表扫描的情况,也可以进行一些优化处理. 即使全表扫描是检索所需数据的唯一可行方法,仍然有多种方法来提升查询性能.优 ...
- 想通过加HINT让其走全表扫描
一个SQL,通过SPM固定它的执行计划,可以通过DBMS_SPM.LOAD_PLANS_FROM_CURSOR_CACHE实现.也可以通地此功能在不修改原SQL的情况下对其加HINT来固定执行计划.D ...
随机推荐
- block的简单使用:点击按钮在另一个控制器内调用block内的代码
1.自定义一个继承于UIButton的按钮 2.声明block: 返回值类型 函数名 参数列表 typedef void (^ButtonBlock)(UIButton *); @interfa ...
- PHPnow开启PHP扩展里openssl支持的方法
PHPnow 是 Win32 下绿色的 Apache + PHP + MySQL 环境套件包.简易安装.快速搭建支持虚拟主机的 PHP 环境.更多介绍<PHP服务套件 PHPnow1.5.6&g ...
- ‘初始化锁相环INIT_PLL()’
在XS128的SCI学习的过程中,INIT_PLL()显得很重要,初始化锁相环几乎在每个程序中都有,今天看的程序-初始化锁相环的相关代码如下: /*************************** ...
- visual studio 2013 快捷键大全、VS2013常用快捷键
Visual Studio 2013 是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具.代码管控工具.集成开发环境(IDE)等等.VS 2013 中新增了很多提高 ...
- Redis 命令 - Lists
BLPOP key [key ...] timeout Remove and get the first element in a list, or block until one is availa ...
- SVN对unity3d项目版本进行管理的不方便问题,研究ing
unity3d项目版本控制遇到些问题,找了以下资料做参考,现在mark一下,以后慢慢解决,之后总结. Unity开启meta. meta:版本控制文件,在新加入项时,Unity3D会产生一个同名的.m ...
- VSFTPD无法上传的解决方法
搭建好FTP之后就没有去测试了,今天去试了一下上传的时候发生错误了,无法上传,提示“553 Could not create file”错误, 上网找了一些资料,发现很多都说是权限和防火墙的问题,但是 ...
- Android之图片窗口和大小调节
结构图: 基类: package ch.halcyon.squareprogressbar.example; import android.app.Activity; import android.a ...
- 百度ueditor编辑器背景不显示问题
网友办法:http://www.hongxuejing.com/hulianwang/ueditor_not_show_background-33.html 官方办法:http://fex-team. ...
- iOS的沙箱目录和文件操作
一.沙箱 iOS的每一个应用程序都有自己的目录来存放数据,这个目录称为沙箱目录.沙箱目录是一种数据安全策略,它设计的原理是只能允许自己的应用访问目录,而不允许其他的应用访问,这样可以保证数据的安全,应 ...