Oracle IO问题解析(六)
2012-05-17 14:08
369 查看
3.2数据文件相关的IO事件
数据库系统中的大多数的IO请求都是针对数据文件的。因此大多数情况下,与数据文件相关的IO事件是引起系统IO性能的主要原因。这些事件也是我们文章需要重点介绍的事件。下面分别针对不同事件介绍问题的解决思路。
3.2.1dbfilesequentialread
这个事件是是最常见的IO等待事件。它一般发生在读取单独数据块时,如读取索引数据块或者通过索引访问一个表数据块,另外在读取数据文件头数据块时也会发生dbfilesequentialread等待事件。
当发现这个等待事件成为系统等待事件中的主要事件,我们可以通过一下方法来处理:
3.2.1.1优化TopSQL
从statspack或者awr报告中的“SQLorderedbyReads”部分或者通过V$SQL视图找出系统中的TopSQL,对SQL进行调优以减少IO请求。
当SQL中存在IndexRangeScan时,如果访问的索引的选择性不好就会导致需要访问过多的数据块,这时可以通过建立一个、或强制SQL使用一个已经存在的选择性更好的索引。这样使我们访问更少的数据块来获取到需要的数据。
如果索引存在碎片,那每个索引数据块上的索引数据就更少,会导致我们需要访问更多的索引数据块。这时,我们需要考虑重建索引来释放碎片;
判断一个所以是否需要重建,我们介绍一个简单的方法:对一个索引进行结构分析后,如果该索引占用超过了一个数据块,且满足以下条件之一:B-tree树的高度大于3;使用百分比低于75%;数据删除率大于15%,就需要考虑对索引重建:
如果使用的索引的聚簇因子(ClusteringFactor)很大,说明一条索引记录指向多个数据块,在返回结果时需要读取更多的数据块。通过重建表可以降低聚簇因子,因而可以在查找索引时减少表数据块的访问块数。
聚簇因子说明了表数据的物理存储位置相对于一个索引的排序性的符合程度。例如,一个非唯一索引是建立在A字段上的,如果表数据的存储是以A字段的顺序存储的,则索引与数据的关系如下图:
此时,索引的聚簇因子很低,从图上看到,假如我们需要获取A=A2的数据,只需要读取一个数据块就可以了;
相反,如果表数据物理存储顺序和索引顺序相差很大,就会出现下面的情况:
这时该索引的聚簇因子就很大,可以看到,如果需要获取A=A2的数据,我们需要读取4块或更多的数据块。
对索引进行分析后,我们可以从视图DBA_INDEXES中获取到索引的聚簇因子,字段名为Clustoring_Factor。如果一个索引是一张表主要被使用的索引(或者是该表的唯一索引),且它的聚簇因子过高导致IO请求过高的话,我们可以考虑采取以下措施来降低IO:
1)以索引字段的顺序重建表以降低聚簇因子,可以用以下语句重建表(当然,你还需要重建触发器、索引等对象,还可能需要重建、重新编译有关联对象):
2)建立基于索引字段IOT(索引表)。
如果该索引不是表的主要索引,只是被少量语句引用到,按照以上方式处理的话反而可能会使其他使用更加频繁的索引的聚簇因子增大,导致系统性能更差。这时我们可以建立包含返回字段的索引,以避免“TABLEACCESSBYINDEXROWID”。如以下例子:
[/code]
通过分区裁剪(partitionpruning)技术来减少的SQL对数据块的访问。
采用分区裁剪技术,Oracle优化器会先分析FROM和WHERE字句,在建立访问分区列表时将那些不会被访问到的分区排除。例如,我们的表T_TEST1的owner字段的值有“SYS、SYSTEM、XDB、DEMO、TEST”,如果我们按照owner字段建立的是分区表:
则对于以下语句:
优化器会先将分区owner_sys、owner_xdb、owner_others从分区访问列表中裁剪出去,只访问分区owner_demo和owner_test上的数据或者通过这两个分区上的索引来访问数据。
3.2.1.2处理非SQL导致的IO问题
如果从statspack或者AWR报告中找不到明显产生dbfilesequentialread事件的SQL,则该等待事件可能是由于以下原因导致的:
热点数据文件或磁盘
数据文件所在的磁盘IO负荷过重导致对IO请求反映慢,这时,我们可以通过statspack或AWR报告中的“FileI/OStatistics”部分(或者通过V$FILESTAT视图)来找到热点磁盘:
Statspackreport:
视图:
找到热点数据文件(磁盘)后,我们可以考虑将数据文件转移到性能更高的存储设备上去,或者利用我们上述说的条带化、RAID等存储技术来均衡IO负荷。
热点数据段
从Oracle9.2开始,出现了数据段的概念。每个表和索引都存储在自己的数据段中。我们可以通过视图V$SEGMENT_STATISTICS查找物理读最多的段来找到热点数据段。通过对热点段的分析,考虑采用重建索引、分区表等方式来降低该数据段上的IO负荷。
另外,我们还可以根据视图v$session_wait中的P1(热点段所在的数据文件号)、P2(发生dbfilesequentialread事件的起始数据块)、P3(数据块的数量,dbfilesequentialread读取数据块数量为1)来定位出热点段:
先找出文件号、起始数据块、数据块数量:
然后根据找出的文件号、起始数据块、数据块数量来定位出数据段:
3.2.1.3调整BufferCache
如果系统中即不存在性能有问题的SQL语句,而且所有磁盘的IO负载也比较均衡(不存在热地磁盘),则我们需要考虑增加BufferCache来降低磁盘IO请求。
在8i,主要是根据缓存命中率(BufferCacheHitRatio)来调整buffercache。当BufferCache调整到一定大小,对命中率没什么影响了时,就没有必要在增大BufferCache了。可以通过以下语句来查看BufferCache命中率:
在9i中,可以利用statspackreport中的BufferCache建议部分来调整BufferCache的大小。
这里,EstPhysicalReadFactor是估算的从磁盘物理读取次数与从buffercache中读取的次数的比值。从意见估算的图表中,当BufferCache的增长对该因子影响不大时,则说明无需在增大BufferCache,我们就可以去相应临界点的大小作为BufferCache的大小。上述例子中,我们可以考虑设置BufferCache大小为2992M。
在Oracle10g中,引入了新的内存管理特性——自动共享内存管理(AutomaticSharedMemoryManagementASMM)。基于这一特性,oracle能够自动根据当前的负荷计算出最优的BufferCache大小。关于ASMM,可以参见文章《Oracle内存全面分析》的SGA_TARGET部分。
我们可以采用多尺寸缓冲池技术将热点数据段(表或索引)KEEP在缓冲池中:
关于多尺寸缓冲的更多内容,可以参考文章《Oracle内存全面分析》的“多缓冲池部分”部分。
3.2.1.4Housekeep历史数据
对于一些被频繁访问到的大表,我们需要定期对其做housekeep,将一些不用的、老的数据从表中移除,以减少访问的数据块。定期对含有时间轴的Transaction表做housekeep是降低IO负载的重要措施。
数据库系统中的大多数的IO请求都是针对数据文件的。因此大多数情况下,与数据文件相关的IO事件是引起系统IO性能的主要原因。这些事件也是我们文章需要重点介绍的事件。下面分别针对不同事件介绍问题的解决思路。
3.2.1dbfilesequentialread
这个事件是是最常见的IO等待事件。它一般发生在读取单独数据块时,如读取索引数据块或者通过索引访问一个表数据块,另外在读取数据文件头数据块时也会发生dbfilesequentialread等待事件。
当发现这个等待事件成为系统等待事件中的主要事件,我们可以通过一下方法来处理:
3.2.1.1优化TopSQL
从statspack或者awr报告中的“SQLorderedbyReads”部分或者通过V$SQL视图找出系统中的TopSQL,对SQL进行调优以减少IO请求。
当SQL中存在IndexRangeScan时,如果访问的索引的选择性不好就会导致需要访问过多的数据块,这时可以通过建立一个、或强制SQL使用一个已经存在的选择性更好的索引。这样使我们访问更少的数据块来获取到需要的数据。
SQL>selectobject_id,object_name
2fromt_test1
3whereowner='SYS'
4andcreated>sysdate-30;
norowsselected
ExecutionPlan
----------------------------------------------------------
Planhashvalue:4014220762
--------------------------------------------------------------------------------
|Id|Operation|Name|Rows|Bytes|Cost(%CPU)
|Time|
--------------------------------------------------------------------------------
|0|SELECTSTATEMENT||1|39|11(0)
|00:00:01|
|*1|TABLEACCESSBYINDEXROWID|T_TEST1|1|39|11(0)
|00:00:01|
|*2|INDEXRANGESCAN|T_TEST1_IDX1|576||1(0)
|00:00:01|
--------------------------------------------------------------------------------
PredicateInformation(identifiedbyoperationid):
---------------------------------------------------
1-filter("OWNER"='SYS'AND"CREATED">SYSDATE@!-30)
Statistics
----------------------------------------------------------
0recursivecalls
0dbblockgets
658consistentgets[/code]
45physicalreads
0redosize
339bytessentviaSQL*Nettoclient
374bytesreceivedviaSQL*Netfromclient
1SQL*Netroundtripsto/fromclient
0sorts(memory)
0sorts(disk)
0rowsprocessed
SQL>createindext_test1_idx2ont_test1(owner,created);
Indexcreated.
SQL>selectobject_id,object_name
2fromt_test1
3whereowner='SYS'
4andcreated>sysdate-30;
norowsselected
ExecutionPlan
----------------------------------------------------------
Planhashvalue:3417015015
---------------------------------------------------------------------------------
|Id|Operation|Name|Rows|Bytes|Cost(%CPU)
|Time|
---------------------------------------------------------------------------------
|0|SELECTSTATEMENT||49|1911|2(0)
|00:00:01|
|1|TABLEACCESSBYINDEXROWID|T_TEST1|49|1911|2(0)
|00:00:01|
|*2|INDEXRANGESCAN|T_TEST1_IDX2|49||1(0)
|00:00:01|
---------------------------------------------------------------------------------
PredicateInformation(identifiedbyoperationid):
---------------------------------------------------
2-access("OWNER"='SYS'AND"CREATED">SYSDATE@!-30)
Statistics
----------------------------------------------------------
1recursivecalls
0dbblockgets
2consistentgets
1physicalreads
0redosize
339bytessentviaSQL*Nettoclient
374bytesreceivedviaSQL*Netfromclient
1SQL*Netroundtripsto/fromclient
0sorts(memory)
0sorts(disk)
0rowsprocessed
如果索引存在碎片,那每个索引数据块上的索引数据就更少,会导致我们需要访问更多的索引数据块。这时,我们需要考虑重建索引来释放碎片;
判断一个所以是否需要重建,我们介绍一个简单的方法:对一个索引进行结构分析后,如果该索引占用超过了一个数据块,且满足以下条件之一:B-tree树的高度大于3;使用百分比低于75%;数据删除率大于15%,就需要考虑对索引重建:
SQL>analyzeindext_test1_idx1computestatistics;
Indexanalyzed.
SQL>analyzeindext_test1_idx1validatestructure;
Indexanalyzed.
SQL>selectbtree_space,--if>8192(块的大小)
2height,--if>3
3pct_used,--if<75
4del_lf_rows/(decode(lf_rows,0,1,lf_rows))*100asdeleted_pct--if>20%
5fromindex_stats;
BTREE_SPACEHEIGHTPCT_USEDDELETED_PCT
------------------------------------------
8800322890
如果使用的索引的聚簇因子(ClusteringFactor)很大,说明一条索引记录指向多个数据块,在返回结果时需要读取更多的数据块。通过重建表可以降低聚簇因子,因而可以在查找索引时减少表数据块的访问块数。
聚簇因子说明了表数据的物理存储位置相对于一个索引的排序性的符合程度。例如,一个非唯一索引是建立在A字段上的,如果表数据的存储是以A字段的顺序存储的,则索引与数据的关系如下图:
此时,索引的聚簇因子很低,从图上看到,假如我们需要获取A=A2的数据,只需要读取一个数据块就可以了;
相反,如果表数据物理存储顺序和索引顺序相差很大,就会出现下面的情况:
这时该索引的聚簇因子就很大,可以看到,如果需要获取A=A2的数据,我们需要读取4块或更多的数据块。
对索引进行分析后,我们可以从视图DBA_INDEXES中获取到索引的聚簇因子,字段名为Clustoring_Factor。如果一个索引是一张表主要被使用的索引(或者是该表的唯一索引),且它的聚簇因子过高导致IO请求过高的话,我们可以考虑采取以下措施来降低IO:
1)以索引字段的顺序重建表以降低聚簇因子,可以用以下语句重建表(当然,你还需要重建触发器、索引等对象,还可能需要重建、重新编译有关联对象):
CREATEnew_tableASSELECT*FROMold_tableORDERBYA;
2)建立基于索引字段IOT(索引表)。
如果该索引不是表的主要索引,只是被少量语句引用到,按照以上方式处理的话反而可能会使其他使用更加频繁的索引的聚簇因子增大,导致系统性能更差。这时我们可以建立包含返回字段的索引,以避免“TABLEACCESSBYINDEXROWID”。如以下例子:
SQL>setautottrace
SQL>selectstatusfromt_test1
2whereowner='DEMO';
576rowsselected.
ExecutionPlan
----------------------------------------------------------
Planhashvalue:4014220762
--------------------------------------------------------------------------------
|Id|Operation|Name|Rows|Bytes|Cost(%CPU)
|Time|
--------------------------------------------------------------------------------
|0|SELECTSTATEMENT||576|6336|11(0)
|00:00:01|
|1|TABLEACCESSBYINDEXROWID|T_TEST1|576|6336|11(0)
|00:00:01|
|*2|INDEXRANGESCAN|T_TEST1_IDX1|576||1(0)
|00:00:01|
--------------------------------------------------------------------------------
PredicateInformation(identifiedbyoperationid):
---------------------------------------------------
2-access("OWNER"='DEMO')
Statistics
----------------------------------------------------------
465recursivecalls
0dbblockgets
222consistentgets
43physicalreads
0redosize
8368bytessentviaSQL*Nettoclient
803bytesreceivedviaSQL*Netfromclient
40SQL*Netroundtripsto/fromclient
8sorts(memory)
0sorts(disk)
576rowsprocessed
SQL>createindext_test1_idx3ont_test1(owner,status)computestatistics;
[/code]
Indexcreated.
SQL>selectstatusfromt_test1
2whereowner='DEMO';
576rowsselected.
ExecutionPlan
----------------------------------------------------------
Planhashvalue:2736516725
--------------------------------------------------------------------------------
|Id|Operation|Name|Rows|Bytes|Cost(%CPU)|Time|
--------------------------------------------------------------------------------
|0|SELECTSTATEMENT||576|6336|2(0)|00:00:01|
|*1|INDEXRANGESCAN|T_TEST1_IDX3|576|6336|2(0)|00:00:01|
--------------------------------------------------------------------------------
PredicateInformation(identifiedbyoperationid):
---------------------------------------------------
1-access("OWNER"='DEMO')
Statistics
----------------------------------------------------------
1recursivecalls
0dbblockgets[/code]
43consistentgets[/code]
3physicalreads[/code]
0redosize
8152bytessentviaSQL*Nettoclient
803bytesreceivedviaSQL*Netfromclient
40SQL*Netroundtripsto/fromclient
0sorts(memory)
0sorts(disk)
576rowsprocessed
通过分区裁剪(partitionpruning)技术来减少的SQL对数据块的访问。
采用分区裁剪技术,Oracle优化器会先分析FROM和WHERE字句,在建立访问分区列表时将那些不会被访问到的分区排除。例如,我们的表T_TEST1的owner字段的值有“SYS、SYSTEM、XDB、DEMO、TEST”,如果我们按照owner字段建立的是分区表:
CREATETABLEt_test1
(object_idNUMBER(5),
object_nameVARCHAR2(30),
ownerVARCHAR2(20),
createdDATE)
PARTITIONBYLIST(owner)
(
PARTITIONowner_sysVALUES('SYS','SYSTEM'),
PARTITIONowner_xdbVALUES('XDB'),
PARTITIONowner_demoVALUES('DEMO'),
PARTITIONowner_testVALUES('TEST'),
PARTITIONowner_othersVALUES(DEFAULT)
);
则对于以下语句:
selectobject_name
fromt_test1
whereownerin('DEMO','TEST')
andcreated>sysdate-30;
优化器会先将分区owner_sys、owner_xdb、owner_others从分区访问列表中裁剪出去,只访问分区owner_demo和owner_test上的数据或者通过这两个分区上的索引来访问数据。
3.2.1.2处理非SQL导致的IO问题
如果从statspack或者AWR报告中找不到明显产生dbfilesequentialread事件的SQL,则该等待事件可能是由于以下原因导致的:
热点数据文件或磁盘
数据文件所在的磁盘IO负荷过重导致对IO请求反映慢,这时,我们可以通过statspack或AWR报告中的“FileI/OStatistics”部分(或者通过V$FILESTAT视图)来找到热点磁盘:
Statspackreport:
TablespaceFilename
----------------------------------------------------------------------------
AvAvAvAvBufferAvBuf
ReadsReads/sRd(ms)Blks/RdWritesWrites/sWaitsWt(ms)
----------------------------------------------------------------------
AFW_DATA/export/home/icssprd/data/data17/icssprd_afw_data_01
72604.31.038100
AFW_INDX/export/home/icssprd/data/data18/icssprd_afw_indx_01
1,74106.31.02,10400
CSS_AN_DATA/export/home/icssprd/data/data03/icssprd_css_an_data
200,64951.83.224,19210
/export/home/icssprd/data/data04/icssprd_css_an_data
242,46261.63.126,985136.7
CSS_AN_INDX/export/home/icssprd/data/data13/icssprd_css_an_indx
70,78925.01.65,33000
CSS_AUDIT_RESOURCES_DATA/export/home/icssprd/data/data10/icssprd_css_audit_r
2,39400.61.01,78100
CSS_AUDIT_RESOURCES_INDX/export/home/icssprd/data/data11/icssprd_css_audit_r
24804.31.05200
......
视图:
SQL>selectb.name,phyrds,phywrts
2fromV$FILESTATa,V$DATAFILEb
3wherea.file#=b.file#;
NAME
--------------------------------------------------------------------------------
PHYRDSPHYWRTS
--------------------
C:\ORACLE\PRODUCT\10.2.0\ORADATA\EDGAR\DATAFILE\O1_MF_SYSTEM_20TFOB4Q_.DBF
13276711565
C:\ORACLE\PRODUCT\10.2.0\ORADATA\EDGAR\DATAFILE\O1_MF_UNDOTBS1_20TFQP78_.DBF
194319924
C:\ORACLE\PRODUCT\10.2.0\ORADATA\EDGAR\DATAFILE\O1_MF_SYSAUX_20TFSGC6_.DBF
659458100811
......
找到热点数据文件(磁盘)后,我们可以考虑将数据文件转移到性能更高的存储设备上去,或者利用我们上述说的条带化、RAID等存储技术来均衡IO负荷。
热点数据段
从Oracle9.2开始,出现了数据段的概念。每个表和索引都存储在自己的数据段中。我们可以通过视图V$SEGMENT_STATISTICS查找物理读最多的段来找到热点数据段。通过对热点段的分析,考虑采用重建索引、分区表等方式来降低该数据段上的IO负荷。
SQL>selectowner,object_name,tablespace_name,object_type,value
2fromV$SEGMENT_STATISTICS
3wherestatistic_name='physicalreads'
4orderbyvaluedesc;
OWNEROBJECT_NAME
------------------------------------------------------------
TABLESPACE_NAMEOBJECT_TYPEVALUE
----------------------------------------------------------
SYSCONTEXT$
SYSTEMTABLE71
SYSI_CONTEXT
SYSTEMINDEX70
......
另外,我们还可以根据视图v$session_wait中的P1(热点段所在的数据文件号)、P2(发生dbfilesequentialread事件的起始数据块)、P3(数据块的数量,dbfilesequentialread读取数据块数量为1)来定位出热点段:
先找出文件号、起始数据块、数据块数量:
SQL>selectp1"fileid",p2"block_id",p3"block_num"
2fromv$session_wait
3whereevent='dbfilesequentialread';
fileidblock_idblock_num
------------------------------
396448691
然后根据找出的文件号、起始数据块、数据块数量来定位出数据段:
SQL>select
2segment_name"SegmentName",
3segment_type"SegmentType",
4block_id"FirstBlockofSegment",
5block_id+blocks"LastBlockofSegment"
6fromdba_extents
7where&fileid=file_id
8and&block_id>=block_id
9and&block_id<=block_id+blocks;
Entervalueforfileid:396
old7:where&fileid=file_id
new7:where396=file_id
Entervalueforblock_id:44869
old8:and&block_id>=block_id
new8:and44869>=block_id
Entervalueforblock_id:44869
old9:and&block_id<=block_id+blocks
new9:and44869<=block_id+blocks
SegmentName
--------------------------------------------------------------------------------
SegmentTypeFirstBlockofSegmentLastBlockofSegment
-------------------------------------------------------------
CSS_TP_SHMT_QUEUE_ACTIVITY
TABLE4484144873
3.2.1.3调整BufferCache
如果系统中即不存在性能有问题的SQL语句,而且所有磁盘的IO负载也比较均衡(不存在热地磁盘),则我们需要考虑增加BufferCache来降低磁盘IO请求。
在8i,主要是根据缓存命中率(BufferCacheHitRatio)来调整buffercache。当BufferCache调整到一定大小,对命中率没什么影响了时,就没有必要在增大BufferCache了。可以通过以下语句来查看BufferCache命中率:
SQL>select1-(physical_reads)/(consistent_gets+db_block_gets)
2fromv$buffer_pool_statistics;
1-(PHYSICAL_READS)/(CONSISTENT_GETS+DB_BLOCK_GETS)
--------------------------------------------------
.95628981
在9i中,可以利用statspackreport中的BufferCache建议部分来调整BufferCache的大小。
BufferPoolAdvisoryforDB:ICSSPRDInstance:icssprdEndSnap:259
->Onlyrowswithestimatedphysicalreads>0aredisplayed
->orderedbyBlockSize,BuffersForEstimate
SizeforSizeBuffersforEstPhysicalEstimated
PEstimate(M)FactrEstimateReadFactorPhysicalReads
-------------------------------------------------------------------
D304.137,7159.185,928,235,496
D608.275,4306.884,443,709,043
D912.3113,1455.733,699,496,220
D1,216.4150,8603.872,502,670,372
D1,520.5188,5752.321,499,049,228
D1,824.6226,2901.701,099,326,418
D2,128.7264,0051.41912,042,579
D2,432.8301,7201.22790,925,174
D2,736.9339,4351.09703,357,378
D2,9921.0371,1951.00645,905,997
D3,0401.0377,1500.99636,992,420
D3,3441.1414,8650.90583,996,250
D3,6481.2452,5800.84542,063,246
D3,9521.3490,2950.79508,261,496
D4,2561.4528,0100.74480,472,150
D4,5601.5565,7250.71455,533,563
D4,8641.6603,4400.67434,743,759
D5,1681.7641,1550.64416,285,837
D5,4721.8678,8700.62400,208,242
D5,7761.9716,5850.60385,785,401
D6,0802.0754,3000.57365,597,932
-------------------------------------------------------------
这里,EstPhysicalReadFactor是估算的从磁盘物理读取次数与从buffercache中读取的次数的比值。从意见估算的图表中,当BufferCache的增长对该因子影响不大时,则说明无需在增大BufferCache,我们就可以去相应临界点的大小作为BufferCache的大小。上述例子中,我们可以考虑设置BufferCache大小为2992M。
在Oracle10g中,引入了新的内存管理特性——自动共享内存管理(AutomaticSharedMemoryManagementASMM)。基于这一特性,oracle能够自动根据当前的负荷计算出最优的BufferCache大小。关于ASMM,可以参见文章《
我们可以采用多尺寸缓冲池技术将热点数据段(表或索引)KEEP在缓冲池中:
SQL>altertablet_test1storage(buffer_poolkeep);
Tablealtered.
关于多尺寸缓冲的更多内容,可以参考文章《
3.2.1.4Housekeep历史数据
对于一些被频繁访问到的大表,我们需要定期对其做housekeep,将一些不用的、老的数据从表中移除,以减少访问的数据块。定期对含有时间轴的Transaction表做housekeep是降低IO负载的重要措施。
相关文章推荐
- Oracle IO问题解析(六)—— 数据文件相关的IO事件
- Oracle IO问题解析(三)
- Oracle IO问题解析
- Oracle IO问题解析(三)—— IO系统的设计和配置(1)
- Oracle IO问题解析(四)
- Oracle IO问题解析(九)
- Oracle IO问题解析(十)
- Oracle IO问题解析
- Oracle IO问题解析
- Oracle IO问题解析(五)
- Oracle IO问题解析(一)—— Oracle中IO的产生
- Oracle IO问题解析
- Oracle IO问题解析
- Oracle IO问题解析
- Oracle IO问题解析(七)
- Oracle IO问题解析(一)
- Oracle IO问题解析【io主文】
- Oracle IO问题解析(七)—— db file scattered read
- Oracle IO问题解析(五)—— Oracle中的IO问题及其解决思路
- Oracle IO问题解析(二)