数据读取

首先数据块读入到Buffer Cache中,并将其放在LRU(Last Recently Used)链表的MRU(Most Recently Used)端,当需要再次访问该块时可以直接从buffer cache中读取,

如果有新的数据需要被读入Buffer Cache中,而Buffer Cache又没有足够的空闲空间,Oracle就根据LRU算法将LRU链表中LRU端的数据置换出去。当这些数据被再次访问到时,需要重新从磁盘读入。

当发生全表扫描(FullTable Scan)时,用户进程读取表的数据块,并将他们放在LRU链表的LRU端(和上面不同,不是放在MRU端)。这样做的目的是为了使全表扫描的数据尽快被移出。因为全表扫描一般发生的频率较低,并且全表扫描的数据块大部分在以后都不会被经常使用到。

而如果你希望全表扫描的数据能被cache住,使之在扫描时放在MRU端,可以通过在创建或修改表(或簇)时,指定CACHE参数。

逻辑读是指从buffercache中读取数据块。可以分为即时读(Current Read)和一致性读(Consistent Read)。注意:逻辑IO只有逻辑读,没有逻辑写。

·                 即时读

即时读即读取数据块当前的最新数据。任何时候在Buffer Cache中都只有一份当前数据块。即时读通常发生在对数据进行修改、删除操作时。这时,进程会给数据加上行级锁,并且标识数据为“脏”数据。

·                 一致性读

Oracle是一个多用户系统。当一个会话开始读取数据还未结束读取之前,可能会有其他会话修改它将要读取的数据。如果会话读取到修改后的数据,就会造成数据的不一致。一致性读就是为了保证数据的一致性。在Buffer Cache中的数据块上都会有最后一次修改数据块时的SCN。如果一个事务需要修改数据块中数据,会先在回滚段中保存一份修改前数据和SCN的数据块,然后再更新Buffer Cache中的数据块的数据及其SCN,并标识其为“脏”数据。当其他进程读取数据块时,会先比较数据块上的SCN和自己的SCN。如果数据块上的SCN小于等于进程本身的SCN,则直接读取数据块上的数据;如果数据块上的SCN大于进程本身的SCN,则会从回滚段中找出修改前的数据块读取数据。通常,普通查询都是一致性读。

查找数据

在一个查询操作中,大量的读操作都产生于数据的查找过程中。减少查找过程是我们优化IO性能问题的重要目标。

下面介绍几种主要的数据查找方式。

·                 Full Table Scan

当查询条件无法命中任何索引、或者扫描索引的代价大于全表扫描代价的某一比例时(由参数optimizer_index_cost_adj设定),Oracle会采用全表扫描的方式查找数据。当发生全表扫描时,Oracle会自下向上一次读取一定数量(由参数db_file_multiblock_read_count设定)的数据块,一直读取到高水位标志(HWM,High Water Mark)下。Full Table Scan会引起db file scattered read事件。

·                 INDEX UNIQUE SCAN

全表扫描查找数据的效率是非常低的。而索引能大幅提高查找效率。普通索引的数据结构是B-Tree,树的叶子节点中包含数据的ROWID,指向数据记录,同时还有指针指向前一个/后一个叶子节点。索引扫描每次读取一个数据块,索引扫描是“连续的”(Sequential)。当索引为UNIQUE索引时,每个叶子节点只会指向一条数据。如果Oracle能预知扫描结果只有0或1条记录时,会采用INDEX UNIQUE SCAN。当对Unique Index中的所有字段进行完全匹配时,会发生INDEX UNIQUE SCAN。

INDEX UNIQUE SCAN的查找过程如下:

1.              从数的根节点数据块开始查找;

2.              查找根节点块中所有key值中大于或等于要查找的值的最小key值;

3.              如果key值大于查找值,则继续查找这个key值之前一个key值所指向的子节点数据块;

4.              如果key值等于查找值,则继续查找这个key值所指向的子节点数据块;

5.              如果没有key值大于或等于查找值,则继续查找最大key值所指向的子节点数据块;

6.              如果继续查找的节点数据块是数一个分支节点,则重复2~4步;

7.              如果查找的节点是叶子节点数据块,则在数据块中查找等于查找值的key值;

8.              如果找到相等的key值,则返回数据和ROWID;

9.              如果没找到相等的key值,则说明没有符合条件的数据,返回NULL。

·                 INDEX RANGE SCAN

如果通过索引查找数据时,Oracle认为会返回数据可能会大于1,会进行INDEX RANGE SCAN,例如Unique Index中字段不完全匹配查找时、非Unique Index查找时。

INDEX RANGE SCAN分为闭包(有前后查找边界)和非闭包(只有一边或者没有边界)。返回数据会依据索引增序排序,多个相同值则会按照ROWID的增序排序。以下的查找条件都是闭包的:

WHERE column = 'Value'

WHERE column like 'value%'

WHERE column between 'value1' and 'value2'

WHERE column in ('value1', 'value2')

以下查找条件非闭包:

WHERE column < 'value1'

WHERE column > 'value2'

闭包条件下的INDEX RANGE SCAN的查找过程如下:

1.              从数的根节点数据块开始查找;

2.              查找根节点块中所有key值中大于或等于要查找的起始值的最小key值;

3.              如果key值大于起始值,则继续查找这个key值之前一个key值所指向的子节点数据块;

4.              如果key值等于起始值,则继续查找这个key值所指向的子节点数据块;

5.              如果没有key值大于或等于起始值,则继续查找最大key值所指向的子节点数据块;

6.              如果继续查找的节点数据块是数一个分支节点,则重复2~4步;

7.              如果查找的节点是叶子节点数据块,则在数据块中大于或等于要查找的起始值的最小key值;

8.              如果Key值小于或等于结束值,则:如果所有Key字段都符合WHERE字句中的查找条件,则返回数据和ROWID;否则继续查找当前叶子节点所指向的右边的叶子节点。

INDEX UNIQUE SCAN和INDEX RANGE SCAN都会引起db file sequential read事件。

·                 TABLE ACCESS BY INDEXROWID

当发生索引扫描时,如果需要返回的字段都在索引上,则直接返回索引上的数据,而如果还需要返回非索引上的字段的值,Oracle则需要根据从索引上查找的ROWID到对应的数据块上取回数据,这时就是TABLE ACCESS BY INDEX ROWID。

·                 INDEX FAST FULL SCAN& INDEX FULL SCAN

索引快速全扫描和全表扫描类似,一次读取db_file_multiblock_read_count个数据块来描所有索引的叶子节点。INDEX FAST FULLSCAN和其他索引扫描不同,它不会从树的根节点开始读取,而是直接扫描所有叶子节点;也不会一次读取一个数据块,而是一次读取db_file_multiblock_read_count个数据块。INDEX FAST FULLSCAN会引起db filescattered read事件。

在某些情况下,如db_file_multiblock_read_count值过小、强制使用索引扫描时,会发生INDEX FULL SCAN。INDEX FULL SCAN和INDEX FAST FULL SCAN不同,它是一种索引扫描,按照B-Tree的查找法从树的根节点开始扫描,遍历整棵树,并且一次读取一个数据块。它会引起db file sequential read事件。

原文地址:http://wsql.iteye.com/blog/1194357

oracle中的数据读取与查找的更多相关文章

  1. DataTable to Excel(使用NPOI、EPPlus将数据表中的数据读取到excel格式内存中)

    /// <summary> /// DataTable to Excel(将数据表中的数据读取到excel格式内存中) /// </summary> /// <param ...

  2. oracle中的数据对象

    oracle中的数据对象有表.视图.索引.序列等 表的相关操作 1.创建表 方式一: 方式二:create table person( create table person1 id number(1 ...

  3. 在Oracle中更新数据时,抛出:ORA-01008: not all variables bound

    在Oracle中更新数据时,抛出了一个 :ORA-01008 not all variables bound, 我的理解是不是所有的变量/参数都有边界,不懂: 后来知道了,原来是“不是所有变量/参数都 ...

  4. MyBatis在Oracle中插入数据并返回主键的问题解决

    引言:  在MyBatis中,希望在Oracle中插入数据之时,同一时候返回主键值,而非插入的条数... 环境:MyBatis 3.2 , Oracle. Spring 3.2   SQL Snipp ...

  5. Sqoop_具体总结 使用Sqoop将HDFS/Hive/HBase与MySQL/Oracle中的数据相互导入、导出

    一.使用Sqoop将MySQL中的数据导入到HDFS/Hive/HBase watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYWFyb25oYWRvb3A=/ ...

  6. Elasticsearch 2.3.2 从oracle中同步数据

    Elasticsearch 2.3.2 从oracle中同步数据   1         数据批量导入-oracle 采用 elasticsearch-jdbc 插件 安装.版本需要ES版本一致 最新 ...

  7. 如何用Excel直接查询Oracle中的数据

    将Oracle中查询的数据保存为Excel文件,通常使用的是PL/SQL Developer. 其实,Excel可直接写SQL语句查询Oracle中数据,在这里,用到ODBC驱动.详细步骤如下: 一. ...

  8. 浅谈Oracle中物理结构(数据文件等。。。)与逻辑结构(表空间等。。。。。)

    初始Oracle时很难理解其中的物理结构和逻辑结构,不明白内存中和硬盘中文件的区别和联系,我也是初学Oracle,这里就简单的谈谈我我看法. 首先,你需要明白的一点是:数据库的物理结构是由数据库的操作 ...

  9. C# 实现Oracle中的数据与Excel之间的转换

    最近项目要求实现数据库之间数据在各个数据库之间导入导出,在此做个笔记 1. 将Oracle中的表导入到Excel中,反之亦然  private static readonly string conne ...

随机推荐

  1. cocos2dx场景切换中init、onEnter、onEnterTransitionDidFinish的调用顺序

    这些方法调用的先后顺序如下(使用 replaceScene 方法): 1. 第2个场景的 scene 方法 2. 第2个场景的 init 方法 3. 第2个场景的 onEnter 方法 4. 转场 5 ...

  2. atoi&itoa

    char* itoa(int num,char*str,int radix) {/*索引表*/ char index[]="0123456789ABCDEFGHIJKLMNOPQRSTUVW ...

  3. (3)Spring定时任务的几种实现

    Spring定时任务的几种实现 近日项目开发中需要执行一些定时任务,比如需要在每天凌晨时候,分析一次前一天的日志信息,借此机会整理了一下定时任务的几种实现方式,由于项目采用spring框架,所以我都将 ...

  4. 【转】【玩转cocos2d-x之二十三】多线程和同步03-图片异步加载

    原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/15334159 cocos2d-x中和Android,Windows都 一样, ...

  5. Ios 程序封装,安装流程

    转:http://www.myexception.cn/operating-system/1436560.html Ios 程序打包,安装流程 一.发布测试,是指将你的程序给   * 你的测试人员,因 ...

  6. Android-AnimationDrawable(二)

    首先可以先定义一个逐帧播放的xml: <?xml version="1.0" encoding="utf-8"?> <animation-li ...

  7. Java Sleep() 与 Wait()的机制原理与区别

    一.概念.原理.区别    Java中的多线程是一种抢占式的机制而不是分时机制.线程主要有以下几种状态:可运行,运行,阻塞,死亡.抢占式机制指的是有多个线程处于可运行状态,但是只有一个线程在运行. 回 ...

  8. android获取手机信息2

    IMEI号,IESI号,手机型号: private void getInfo() { TelephonyManager mTm = (TelephonyManager) getSystemServic ...

  9. 七中滤波方法测试matlab实现

    http://blog.163.com/xiaheng0804@126/blog/static/1205282120132129471816/ 创建两个混合信号,便于更好测试滤波器效果.同时用七中滤波 ...

  10. [持续更新]android stduio的一些小技巧

    1.导入第三方jar 无法和eclipse一样可以直接刷新就可以导入libs里的jar,要到jar文件上右键按add jar. 2.其他依赖项目里有support-v4包的时候 在Libs里还是要有s ...