Oracle之 db file sequential read等待事件优化思想

为什么db file sequential read事件在full table scan操作中显现,为什么在多块读中为什么会有单块读存在 ?

extent的大小 :当扩展区中的最后一组块仅是1个块,Oracle使用单块读来提取这个块。这正常来说不是一个问题,除非你扩展区尺寸太小。以下是一个event 10046的trace文件,显示在全表扫描操作中包围的db file sequential read事件。表块尺寸是8K,MBRC是8个块,扩展区尺寸是72K(9个块)。如果表是大的,对表的全表扫描将导致许多db file sequential read事件。如果是这种情况,全表扫描操作将完成的较快,如果表以一个较大的扩展区尺寸重建的话。

cached block: 在multiblock读的一组中的1个或多个块已经在buffer cache中了,因此oracle把fetch分割成2个或多个读,它可以有单块或多块I/O组成。例如,如果MBRC是8,块3和块7是在buffer cache中,oracle将提出3个读呼叫――第一个是块1和块2,第二个是块4 和块6,第三个是块8。因此第三个fetch是单数据块,等待事件就是db file sequential read。然而,对于前2个读呼叫,这等待事件是db file scattered read,因为块的数量是超过1的。因此,被缓存的块能导致全表扫描操作来执行比所需更多的读。

chained or migrated rows: 这就是一个问题,当sql语句的执行计划请求一个全表扫描的时候,如果你看到很多对该表的db file sequential read等待。这象征了表有许多链接或移植的行。Oracle使用单块读i/o来访问每一个链接的或移植的行。检查在DBA_TABLES视图中的表的CHAIN_CNT。当然,CHAIN_CNT是LAST_ANALYZED日期开始的。被移植的行能通过重组表来纠正(譬如export和import,或alter table move)。

补充:
行迁移 成因 :当发出update导致记录行长增加,block的剩余空间不足以存放这条记录,就会产生行迁移,发生行迁移时rowid不会改变,原来的block 中会用一个指针存放这条记录在新的block中的地址,发生行迁移会对性能产生影响,因为读这条记录会读两个BLOCK。

行链接 成因 :当一个BLOCK不足以存放下一条记录的时候,就会发生行连接,这个时候oracle会把这条记录分成几个部分,分别存放在几个block中,然后把这几个block chain起来。行连接同样会影响性能,因为读一条记录至少会读两个BLOCK.

index entry creation : 它不是一个问题,当你在sql语句执行计划呼叫一个全表扫描的时候,如果你看见许多针对index的db file sequential read等待。在以下例子中,TABLE_A有一个索引,db file sequential read等待是读index块到SGA来充满来自TABLE_B数据的结果。注意db file sequential read等待与db file scattered read统计数据上比较的数量。这暗示你不能再假设你将从执行计划上就能看到是哪个瓶颈。许多DBAs希望看到许多db file scattered read事件。另一个一文不值的观点就是db file sequential read等待事件不会应用于insert语句。一般的误解就是它仅应用到update和delete语句。


解决对策:

1、应用程序层
需要筛选出主要发生db file scattered read等待的sql语句。如果不必要的执行FTS或Index Full San,修改sql语句或创建更合理的索引就可以解决。大量读取数据时多数情况下FTS性能更好。不是盲目的创建索引,而是要考虑相应的sql语句后,判断FTS有利,还是Index Full San有利。

2、oracle内存层
如果高速缓存区过小,就会反复需要物理I/O,相应的db file scattered read等待也会增加。这时free buffer waits等待事件一同出现的几率较高。FTS引起的db file scattered read等待的严重性不仅在于需要I/O,而且在于降低高速缓存区的效率,进而影响会话工作。从这种角度出发,处理FTS的有效方法之一就是使用多重缓冲池。读取一次后不再使用的数据,有必要保存到高速缓存区从而导致影响其他用户的工作吗?多重缓冲池虽然是有效管理高速缓存区的强有力的方法,但是遗憾的是没有被广泛使用。多重缓冲池从三个方面改善高速缓存区的性能。第一,将经常访问的对象保存与内存,进而将物理I/O最小化。第二,临时性数据所占用的内存被快速的重新使用,进而将内存的浪费最小化。第三,因为每个缓冲池各使用不同的cache buffers lru chain锁存器,所以有减少锁存器争用的效果。指定DEFAULT将适用默认的缓冲池。这个选项适用于没有分配给KEEP缓冲池和RECYCLE缓冲池的其它数据库对象。通常将经常访问的对象放入KEEP缓冲池中,指定KEEP将把数据块放入KEEP缓冲池中。维护一个适当尺寸的KEEP缓冲池可以使Oracle在内存中保留数据库对象而避免I/O操作。通常将偶尔访问的大表放入RECYCLE缓冲池中,指定RECYCLE将把数据块放入RECYCLE缓冲池中。一个适当尺寸的RECYCLE缓冲池可以减少默认缓冲池为RECYCLE缓冲池的数据库对象的数量,以避免它们占用不必要的缓冲空间。
有效使用FTS的另一种方法是将db_file_multiblock_read_count参数值提高。这个参数决定执行Multi Block I/O时一次读取的块数。因此这个值高,FTS速度相应也会提升,而且db file scattered read等待也会相应减少。将这个值在全系统级上设定得高,并不太妥当。最好是利用alter session set ...命令,只在执行sql语句期间提升这个值。因为这个值如果升高,有关FTS的费用会算的较低,可能会导致sql执行计划的变更。
较大的块也是提高FTS性能的方法。较大的块在如下两个方面改善FTS的性能。第一,增加一个块所包含的行数,这样相同大小的表时使用更少的块数,相应的Multi Block I/O次数也会减少。第二,块的大小较大,则发生行链接或行迁移的概率会降低,附加的I/O也随之降低。大部分OLTP系统上一般只是用标准块大小(8K)。但是经常扫描大量数据的OLAP上使用更大的块能改善性能。

3、oracle段层

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/12699c3d84b318a642add3e16e1b068a.html