想关注我吗?请点击图片上方蓝字小麦苗关注即可,关注后您将可以每日获得最实用的数据库技术。请将小麦苗公众号置顶,小麦苗不喜欢被压着,~O(∩_∩)O~
荣
作者小麦苗的今日寄语
多
只有经历了红尘中的善恶是非,爱恨恩仇,才能领悟真正的大道真谛,把人生悟透,将人世看懂,是学道必须的一步。天地间,道大,人也大。人生本来就是,上山,下山。而道心原本宽广,可容万物,装得下山河大地,万古星辰。
---- 摘自《道士下山》
各位粉丝朋友,从8月13日开始,小麦苗打算花很长很长的一段时间来给大家分享有关自己整理的等待事件的学习笔记,有的内容来自于网络,大家有什么问题可以留言,欢迎交流。
今天给大家分享的是等待事件中的User I/O 类等待事件之db file sequential read(数据文件顺序读)
dbfile sequential read这个等待事件在实际生产库非常常见,是个与UserI/O相关的等待事件,通常显示与单个数据块相关的读取操作,在大多数情况下,读取一个索引块或者通过索引读取一个数据块时,都会记录这个等待。当Oracle需要每次I/O只读取单个数据块这样的操作时,会产生这个等待事件。最常见的情况有索引的访问(除IFFS外的方式),回滚操作,以ROWID的方式访问表中的数据,重建控制文件,对文件头做DUMP等。
在V$SESSION_WAIT这个视图里面,这个等待事件有三个参数P1、P2、P3,其中P1代表Oracle要读取的文件的绝对文件号即File#,P2代表Oracle从这个文件中开始读取的起始数据块的BLOCK号即Block#,P3代表Oracle从这个文件开始读取的BLOCK号后读取的BLOCK数量即Blocks,通常这个值为1,表明是单个BLOCK被读取,如果这个值大于1,则是读取了多个BLOCK,这种多BLOCK读取常常出现在早期的Oracle版本中从临时段中读取数据的时候。
这个等待事件有三个参数:
File#: 要读取的数据块所在数据文件的文件号。
Block#: 要读取的起始数据块号。
Blocks:要读取的数据块数目(这里应该等于1)。
SELECT*
FROMv$event_name
WHERENAME='db file sequential read';
在Oracle 10g中,这个等待事件被归入User I/O一类:
这一事件通常显示与单个数据块相关的读取操作(如索引读取)。如果这个等待事件比较显著,可能表示在多表连接中,表的连接顺序存在问题,可能没有正确的使用驱动表;或者可能索引的使用存在问题,不加选择地进行索引,并非索引总是最好的选择。
这里的sequential也并非指的是Oracle按顺序的方式来访问数据,和db file scattered read一样,它指的是读取的数据块在内存中是以连续的方式存放的。
在大多数的情况下读取一个索引数据的BLOCK或者通过索引读取数据的一个BLOCK的时候都会去要读取相应的数据文件头的BLOCK。在早期的版本中会从磁盘中的排序段读取多个BLOCK到高速缓存区的连续的缓存中。
在大多数情况下,通过索引可以更为快速地获取记录,所以对于一个编码规范、调整良好的数据库,这个等待事件很大通常是正常的。有时候这个等待过高和存储分布不连续、连续数据块中部分被缓存有关,特别对于DML频繁的数据表,数据以及存储空间的不连续可能导致过量的单块读,定期的数据整理和空间回收有时候是必须的。但是在很多情况下,使用索引并不是最佳的选择,比如读取较大表中大量的数据,全表扫描可能会明显快于索引扫描,所以在开发中就应该注意,对于这样的查询应该避免使用索引扫描。
如果这个等待事件在整个等待时间中占主要的部分,可以采用以下的几种方法来调整数据库。
方法一:从AWR的报告中的"SQL ordered by Reads"部分或者从V$SQL视图中找出读取物理磁盘I/O最多的几个SQL语句,优化这些SQL语句以减少对I/O的读取需求。
如果有Index Range scans,但是却使用了不该用的索引,就会导致访问更多的BLOCK,这个时候应该强迫使用一个可选择的索引,使访问同样的数据尽可能的少的访问索引块,减少物理I/O的读取;如果索引的碎片比较多,那么每个BLOCK存储的索引数据就比较少,这样需要访问的BLOCK就多,这个时候一般来说最好把索引rebuild,减少索引的碎片;如果被使用的索引存在一个很大的Clustering Factor,那么对于每个索引BLOCK获取相应的记录的时候就要访问更多表的BLOCK,这个时候可以使用特殊的索引列排序来重建表的所有记录,这样可以大大的减少Clustering Factor,例如:一个表有A,B,C,D,E五个列,索引建立在A,C上,这样可以使用如下语句来重建表:
CREATE TABLE TABLE_NAME AS SELECT * FROM old ORDER BY A,C;
此外,还可以通过使用分区索引来减少索引BLOCK和表BLOCK的读取。
方法二:如果不存在有问题的执行计划导致读取过多的物理I/O的特殊SQL语句,那么可能存在以下的情况:
数据文件所在的磁盘存在大量的活动,导致其I/O性能很差。这种情况下可以通过查看AWR报告中的"File I/O Statistics"部分或者V$FILESTAT视图找出热点的磁盘,然后将在这些磁盘上的数据文件移动到那些使用了条带集、RAID等能实现I/O负载均衡的磁盘上去。
使用如下的查询语句可以得到各个数据文件的I/O分布:
SELECTd.nameNAME,
f.phyrds,
f.phyblkrd,
f.phywrts,
f.phyblkwrt,
f.readtim,
f.writetim
FROMv$filestat f,
v$datafile d
WHEREf.file#=d.file#
ORDERBYf.phyrdsDESC,
f.phywrtsDESC;
从Oracle9.2.0开始,我们可以从V$SEGMENT_STATISTICS视图中找出物理读取最多的索引段或者是表段,通过查看这些数据,可以清楚详细的看到这些段是否可以使用重建或者分区的方法来减少所使用的I/O。如果Statpack设置的level为7就会在报告中产生"Segment Statistics"的信息。
SELECTstatistic_name,
COUNT(1)
FROMv$segment_statistics T
GROUPBYT.STATISTIC_NAME;
从上面的查询可以看到相应的统计名称,使用下面的查询语句就能得到读取物理I/O最多的段:
SELECTobject_name,
object_type,
statistic_name,
VALUE
FROMv$segment_statistics
WHEREstatistic_name='physical reads'
ORDERBYVALUEDESC;
方法三:如果不存在有问题的执行计划导致读取过多的物理I/O的特殊SQL语句,磁盘的I/O也分布的很均匀,这种时候我们可以考虑增大的高速缓存区。对于Oracle8i来说增大初始化参数DB_BLOCK_BUFFERS,让Statpack中的Buffer Cache的命中率达到一个满意值;对于Oracle9i来说则可以使用Buffer Cache Advisory工具来调整Buffer Cache;对于热点的段可以使用多缓冲池,将热点的索引和表放入到KEEP Buffer Pool中去,尽量让其在缓冲中被读取,减少I/O。