db file sequential read 详解

db file sequential read (本文由thomaswoo_dba翻译,转载请注明出处)

db file sequential read 事件有三个参数:file#,first block#, block count, 在oracle 10g里,此等待事件在归于 User I/O wait class 下面的. 处理db file sequential read 事件要牢牢把握下面三个主要思想:
1)oracle 进程需要访问的block不能从SGA 中获取,因此oracle 进程会等待block从I/O读到SGA
2)两个重要参数TIME_WAITED,AVERAGE_WAIT,是以单个session获取的
3)影响较大的db file sequential read 一般很像应用程序问题

Common Causes, Diagnosis, and Actions

db file sequential read 等待事件被SQL 语句初始化,主要从index,rollback(or undo) segments, tables(通过rowid访问表),control files 和data file headers中进行single-block read.

访问数据对象(table,index)总是会产生Physical I/o需求,当出现db file sequential read等待事件时,并不意味着数据库产生系统问题,基至它大量出现都不是一件坏事.真正要引起注意的是像enqueue 和latch free等待事件,它们总是引起系统性题的根源.并且它们使single-block(单块读取)变得因难了.

那么什么情况下, 当出现db file sequential read等待事件,才可以视为性能问题呢?
什么情况下,db file sequential read可以视为系统的超额负担,并且基准线应该怎样去定义?
这是一个比较复杂的问题.在没有工业标准指引的情况下.我们要依据数据库运行环境来制定标准线.
比如,我们定义超过多少时间的db file sequential read等待事件,可以视为性能问题,还可以用最原始的方法,那就是等待用户抱怨.

在V$SESSION_EVENT视图中,db file sequential read的高TIME_WAITED是较为容易发现的,当时因为V$SESSION_EVENT是记录从实例启动以来的数据,所以我们同以前的TIME_WAITED进行比较,当然跟同一个session,同一个LOGON_TIME的非空闲事件进行比较是可以的,也是比较准确的.当实例不间断运行很长一段时间(数天或数星期)之后,TIME_WAITED的累计值就会很高,这当然不能说是性能问题.

select a.sid,
a.event,
a.time_waited,
a.time_waited / c.sum_time_waited * 100 pct_wait_time,
round((sysdate - b.logon_time) * 24) hours_connected
from v$session_event a, v$session b,
(select sid, sum(time_waited) sum_time_waited
from v$session_event
where event not in (
'Null event',
'client message',
'KXFX: Execution Message Dequeue - Slave',
'PX Deq: Execution Msg',
'KXFQ: kxfqdeq - normal deqeue',
'PX Deq: Table Q Normal',
'Wait for credit - send blocked',
'PX Deq Credit: send blkd',
'Wait for credit - need buffer to send',
'PX Deq Credit: need buffer',
'Wait for credit - free buffer',
'PX Deq Credit: free buffer',
'parallel query dequeue wait',
'PX Deque wait',
'Parallel Query Idle Wait - Slaves',
'PX Idle Wait',
'slave wait',
'dispatcher timer',
'virtual circuit status',
'pipe get',
'rdbms ipc message',
'rdbms ipc reply',
'pmon timer',
'smon timer',
'PL/SQL lock timer',
'SQL*Net message from client',
'WMON goes to sleep')
having sum(time_waited) > 0 group by sid) c
where a.sid = b.sid
and a.sid = c.sid
and a.time_waited > 0
and a.event = 'db file sequential read'
order by hours_connected desc, pct_wait_time;
(本条语句来源于OWI 材料,但是本SQL语句计算的结果是不精确的,因为session sid是时时改变的)

减少db file sequential read 等待事件,我们可以从两方面入手:
1)第一条当然是优化SQL语句,以减少物理读和逻辑读
2)第二条是从统计上减少平均等待时间(比如优化最高wait_time的等待事件)
备注:特别是给客户看结果时效果最明显,因为图形给人的感观是比较明显的

相对每一条来说,除非用你10046事件或自己做一个不间断等待事件程序,不然是非常难以锁定哪一条SQL引起长时间的wait_time.退一步讲,当前的SQL也不一定就是引起wait_time的原因.所以我们发现要解决等待事件的问题没有历史数据是很困难的.

你也可以通过查询V$SQL视图获取平均DISK_READS,当然我们不能就认为此SQL就属于某个SESSION,所以下次对session进行trace,一般可以定位SQL,然后优化SQL以减少物理读与逻辑读.

备注:除了DISK_READS之外,oracle 10g为V$SQL 和V$SQLAREA视图增加了一些另人兴奋不己的新列:
USER_IO_WAIT_TIME
DIRECT_WRITES
APPLICATION_WAIT_TIME
CONCURRENCY_WAIT_TIME
CLUSTER_WAIT_TIME
PLSQL_EXEC_TIME
JAVA_EXEC_TIME
当然我们通过高累计的USER_IO_WAIT_TIME去定位SQL是可能的,但V$SQL和V$SQLAREA两个视图的访问速度是较慢的.
另外可以减少db file sequential read等待事件影响的方法是减少AVERAGE_WAIT ,AVERAGE_WAIT列是一个session等待single block被从硬盘获取的平均等待时间(英文好读,中文有点扭,主要我的水平不够)
This is the average time a session has to wait for a single block fetch from disk(英文原句).AVERAGE_TIME是V$SESSION_EVENT视图中的列.在高速的存储系统中,平均的single-block读不能够超过10ms(milliseconds,千分之一秒) 或1cs(centiseconds,百分之一秒).一般的情况下,SAN(storage area network,网络存储)的AVERAGE_TIME平均等待事间在4至8ms之间,因为SAN的cache都较大.
AVERAGE_TIME的值越大,single-block读的系统资源开耗也随之增大,也即进程的响应时间会受到影响.

从另外一个方面来讲,较低的AVERAGE_TIME值反应进程等待single-block读的时间会较短.当然
AVERAGE_TIME调优的优先级远没有SQL优化的优先级高,因为优化一个占用大量资源的SQL的效果是非常明显和有效的.

需要注意的db file sequential read 并不总是对index对像进行资源占用,有时也会对table/partition对像进行资源占用.所以我们需要将P1/P2参数的值进行转换,在此我们会用到视图DBA_EXTENTS以获取对像名.
但是DBA_EXTENTS是一个复杂的,响应极慢的视图.要想用快一点的方法,X$和DBA_OBJECTS将是一个更好的选择.因为X$BH不占用BUFFER_CACHE所以,访问X$BH会有I/O产生,还有就是DBA-OBJECTS视图不包括rollback 和undo 段,所以如果db file sequential read访问这两个对象,也是不能被解析的.
查询的例子:

select b.sid,       nvl(substr(a.object_name,1,30),                  'P1='||b.p1||' P2='||b.p2||' P3='||b.p3) object_name,       a.subobject_name,       a.object_typefrom   dba_objects a, v$session_wait b, x$bh cwhere  c.obj = a.object_id(+)and    b.p1 = c.file#(+)and    b.p2 = c.dbablk(+)and    b.event = 'db file sequential read'unionselect b.sid,       nvl(substr(a.object_name,1,30),                  'P1='||b.p1||' P2='||b.p2||' P3='||b.p3) object_name,       a.subobject_name,       a.object_typefrom   dba_objects a, v$session_wait b, x$bh cwhere  c.obj = a.data_object_id(+)and    b.p1 = c.file#(+)and    b.p2 = c.dbablk(+)and    b.event = 'db file sequential read'order  by 1;

SID OBJECT_NAME               SUBOBJECT_NAME            OBJECT_TYPE----- ------------------------- ------------------------- -----------------   12 DVC_TRX_REPOS             DVC_TRX_REPOS_PR64        TABLE PARTITION  128 DVC_TRX_REPOS             DVC_TRX_REPOS_PR61        TABLE PARTITION  154 ERROR_QUEUE               ERROR_QUEUE_PR1           TABLE PARTITION  192 DVC_TRX_REPOS_1IX         DVC_TRX_REPOS_20040416    INDEX PARTITION  194 P1=22 P2=30801 P3=1  322 P1=274 P2=142805 P3=1  336 HOLD_Q1_LIST_PK                                     INDEX
像本例中的object_type,如果是table,要进SQL进行相应的优化.
Sequential Reads Against Indexes
db file sequential read 主要的问题不是对index的访问,而且超额的对错误index的访问.当系统的访问路径发生更改时,可能对效能慢的index进行访问,从而产生等待.当然如果一个SQL执行了大量的index读这也可能是一个性能问题.所以分析SQL的执行计划是一个比较好的方法,当要用FULL TABLE SCAN时,用index就会产生性能问题.还有就是FIRST_ROWS 和ALL_ROWS的问题,当然从大的方面讲OLTP与DSS的混用也会产生不合时适的db file sequential read.还有关于驱动表(driving table)的问题.不对的驱动表,性能也不会好.
记住,所有的努力的目的应该是一样的,那就是降低logical and physical I/Os
下面有个种方法:1)分析SQL,弄清SQL的逻辑,看看SQL到底想获取什么,然后优化,甚至重写2)将index放在快磁盘上,尤其不要放在RAID-5上,因为慢磁盘导致高average time,然而I/O优化的优先级  不可以高于SQL CODE的优化.因为SQL有问题再快的磁盘的也不行,最好用OUTLINE稳固执计计划,尤其是第三方软件3)关于index表,最好将数据进行排列,以减少I/O.可以通过DBA_INDEXS.CLUSTERING_FACTOR来查看index有没有达到  表的所有块的数量,如有是,说明大部份列是排列的,如是不是,表时表是随机排列的.这时可以通过重组表以解决问题.4)看看表最近没有没建立新的index,使SQL的执行计划发生改变.(下面的语句可以查看到)  看看有没有invalid的index.
select owner,        substr(object_name,1,30) object_name,        object_type,        created   from   dba_objects   where  object_type in ('INDEX','INDEX PARTITION')   order by created;
5)OPTIMIZER_INDEX_COST_ADJ 和OPTIMIZER_INDEX_CACHING
(来源于网上)其次,由于测试环境的不同,Tom的测试结果是在缺省值(100)的环境下,就已经和上面取值500时一样了,即对T2全表扫描而T1使用索引。Tom试验中,减小取值直至0,访问路径就变成使用两个索引,而并不会出现均不使用索引的情况。除去系统的不同(可能导致取缺省值时访问路径是否一致),只看变化趋势,显然10g中灵活性更高,1-10000的取值使得CBO可以覆盖所有的访问路径。另一方面,正如Tom的结论所说,OPTIMIZER_INDEX_COST_ADJ的取值越大,优化器越倾向于使用全表扫描,取值越小,优化器越倾向于使用索引。                 再次,我们对比相同访问路径下的不同点。在取值从1变化到200(1-50-100-200)的过程中,优化器计算出的代价是持续增长的,而从1000到10000则是不变的。这说明这个参数与索引I/O的代价有关,而和全表扫描并无关系,这与Tom所说的并不矛盾,不过显然更精确一点。                 最后我们其实应该看到,虽然有如上所说的代价变化问题,同一访问路径下实际的运行性能并无区别,由于数据量比较小,上面的例子也许不能很好的说明这一点,不过想想Oracle用相同的路径去执行,也没有理由不同性能吧。              OPTIMIZER_INDEX_CACHING值为0,值越大,系统越tendence去用nested loops .Find out what values the sessions are running with. Up to Oracle9i Database, this information could only be obtained by tracing the sessions with the trace event 10053 at level 1 and examining the trace files. In Oracle Database 10g, this is as simple as querying the V$SES_OPTIMIZER_ENV view.可以通过10053事件查看SESSION相应的OPTIMIZER_INDEX_COST_ADJ 和OPTIMIZER_INDEX_CACHING值是多少,在10g中省不了事,直接查V$SES_OPTIMIZER_ENV视图就可以了,下面的是例子:
select * FROM V$SES_OPTIMIZER_ENV  WHERE NAME=LOWER('OPTIMIZER_INDEX_COST_ADJ') or                                          name=lower('OPTIMIZER_INDEX_CACHING');
SID   ID    NAME                       ISDEFAULT  VALUE--------------------------------------------------------144   67    optimizer_index_caching    YES        0145   66    optimizer_index_cost_adj   YES        100145   67    optimizer_index_caching    YES        0
因为oracle的optimizer依赖于表与索引的statistics,所以要确保现在的statistics能够代表现有数据,不正确的statistics会让optimizer 产生低效的执行计划,当然statistics也不必天天更新,因为这样的话,执行计划就也会天天更新,这对性能问题的分析会产生干扰
System-Level Diagnosis
V$SYSTEM_EVENT视图为系统级别的诊断提供数据,基中AVERAGE_TIME和TIME_WAITED与I/O相关事件关联记住TIME_WAITED只是记录自实例启动以来的记录,当实例运行比较长的一段时间后,db file sequential read 通常较高.当然,经常查询V$SYSTEM_EVENT并且以TIME_WAITED排序,能够通过相互比较而找到比较明显的等待事件.当db file sequential read 不位于top five时,不要担心,因为可能有更大的问题要去发现当db file sequential read 位于top five时,也总能说明数据库进行了大量的single-block读.这里可以看系统级别的诊断能力是非常受限的.但事件总是两面情,这里却可以看系统硬件上瓶颈这在v$session_wait事件里可是看不到的.当你想升级系统,可是你的直接上司要求你提供系统瓶颈报告时,下面就是那个好办法:
select a.event,        a.total_waits,        a.time_waited,        a.time_waited/a.total_waits average_wait,  这里的average_wait是很用的       sysdate – b.startup_time days_oldfrom   v$system_event a, v$instance border by a.time_waited;  当average single-block读超过你所定的阀门的时候,你要看看I/O子系统是不是得到优化了.当然用操作系统的I/O控制命令(iostat,vmstat)去监控硬盘,可以发现I/O的瓶颈,可以去评估各I/O子系统之间是不是平衡.Device:                  tps         Blk_read/s         Blk_wrtn/s         Blk_read         Blk_wrtndev8-0                  3.93              17.03              34.66         54592552  111099454dev8-1                 12.08              56.68              99.93  181659920  320286944dev8-2                 23.38             194.11             189.93  622154550  608747464dev8-3                 16.00             230.43             128.04  738570544  410383416dev8-4                  4.73              59.89              80.98  191965458  259557752通过上例,可以看到dev8-2,dev8-3的块读写是远远超过其它的,所以可以考虑平衡一下I/O
另外,除了从V$SYSTEM_EVENT视图中进行系统级别的db file sequential read average wait之外,oracle也提供了另外一个视图v$filestat来获取single-block读的统计数据.

select a.file#,        b.file_name,        a.singleblkrds,        a.singleblkrdtim,        a.singleblkrdtim/a.singleblkrds average_waitfrom   v$filestat a, dba_data_files b where  a.file# = b.file_id   and    a.singleblkrds > 0order by average_wait;

FILE# FILE_NAME                     SINGLEBLKRDS SINGLEBLKRDTIM AVERAGE_WAIT----- ----------------------------- ------------ -------------- ------------   367 /dev/vgEMCp113/rPOM1P_4G_039          5578            427   .076550735  368 /dev/vgEMCp113/rPOM1P_4G_040          5025            416    .08278607  369 /dev/vgEMCp113/rPOM1P_4G_041         13793           1313   .095193214  370 /dev/vgEMCp113/rPOM1P_4G_042          6232            625   .100288832  371 /dev/vgEMCp113/rPOM1P_4G_043          4663            482   .103366931  372 /dev/vgEMCp108/rPOM1P_8G_011        164828         102798   .623668309  373 /dev/vgEMCp108/rPOM1P_8G_012        193071         125573    .65039804  374 /dev/vgEMCp108/rPOM1P_8G_013        184799         126720   .685717996  375 /dev/vgEMCp108/rPOM1P_8G_014        175565         125969   .717506337

其中SINGLEBLKRDTIM是centiseconds(本篇完)
时间: 2024-07-30 18:36:43

db file sequential read 详解的相关文章

详解 db file sequential read 等待事件

db file sequential read (本文由thomaswoo_dba翻译,转载请注明出处) db file sequential read 事件有三个参数:file#,first block#, block count, 在oracle 10g里,此等待事件在归于 User I/O wait class 下面的. 处理db file sequential read 事件要牢牢把握下面三个主要思想: 1)oracle 进程需要访问的block不能从SGA 中获取,因此oracle 进

常识之外:全表扫描为何产生大量 db file sequential read 单块读?

原创 2016-07-05 熊军 Oracle   编辑手记:在理解Oracle技术细节时,我们不仅应该读懂概念,还要能够通过测试验证细节,理解那些『功夫在诗外』的部分,例如全表扫描和单块读. 开发人员在进行新系统上线前的数据校验测试时,发现一条手工执行的 SQL 执行了超过1小时还没有返回结果.SQL 很简单: 下面是这条 SQL 的真实的执行计划: 很显然,在这个表上建 billing_nbr 和 start_date 的复合索引,这条 SQL 就能很快执行完(实际上最后也建了索引).但是这

db file sequential read及优化

db file sequential read:直接路径读:   官方说明如下: This event signifies that the user process is reading a buffer into the SGA buffer cache and is waiting for a physical I/O call to return. A sequential read is a single-block read. Single block I/Os are usuall

Resolving Issues Where Application Queries are Waiting Too Frequently for 'db file sequential read'

昨天有篇"db file sequential read"的介绍,还有一篇类似的:Resolving Issues Where Application Queries are Waiting Too Frequently for 'db file sequential read' Operations (文档 ID 1475825.1) 诊断"db file sequential read"的步骤: 简述: 低效的SQL会引起不同节点间非常多的块读. 问题确认: 花

High Waits on 'Db File Sequential Read' Due to Table Lookup Following Index Access

最近某些系统AWR的top 5中"Db File Sequential Read"占据的时间百分比非常大,通常这种等待事件是一种正常的.但当前系统性能是有些问题的,并发量大,有些缓慢,因此需要判断这种等待事件是否能够减少.MOS有几篇关于这种等待事件的介绍,这是其中一篇. High Waits on 'Db File Sequential Read' Due to Table Lookup Following Index Access (文档 ID 875472.1) 即使执行计划已经

db file sequential read等待事件

最近某个应用的AWR中总显示"db file sequential read"等待事件位于top 5之首,下面检索下MOS关于这个等待事件的说明. 等待事件: "db file sequential read" Reference Note (文档 ID 34559.1)         这种等待事件是一种IO读请求相关的等待.与"db file scattered read"不同,因为"sequential read"是将数

Android的file文件操作详解

  android的文件操作要有权限: 判断SD卡是否插入 Environment.getExternalStorageState().equals( android.os.Environment.MEDIA_MOUNTED); 获得sd卡根目录 File skRoot = Environment.getExternalStorageDirectory(); 获得私有根目录 File fileRoot = Context.getFilesDir()+""; 确定或获得文件夹和文件路径

解决db file sequential read与db file scattered read

1.根据收集的等待事件,分析是那些对象以及对应的sql. 2.确定是那些对象,执行如下: SELECT segment_name, partition_name, p1, p2 FROM dba_extents, wait1 WHERE wait1.p2 BETWEEN block_id AND (block_id + blocks - 1) AND file_id = wait1.p1ORDER BY segment_name 3.确定执行的sql语句,执行如下: SELECT hash_va

Oracle Statspack分析报告详解

statspack 输出结果中必须查看的十项内容 1.负载间档(Load profile) 2.实例效率点击率(Instance efficiency hit ratios) 3.首要的5个等待事件(Top 5 wait events) 4.等待事件(Wait events) 5.闩锁等待 6.首要的SQL(Top sql) 7.实例活动(Instance activity) 8.文件I/O(File I/O) 9.内存分配(Memory allocation) 10.缓冲区等待(Buffer