这几天每天下午3点开始,开发人员反应Oracle慢,第一等待事件是read by other session
Top 5 Timed Foreground Events
Event | Waits | Time(s) | Avg wait (ms) | % DB time | Wait Class |
---|---|---|---|---|---|
read by other session | 4,914,569 | 9,987 | 2 | 45.17 | User I/O |
db file sequential read | 3,176,031 | 7,473 | 2 | 33.80 | User I/O |
DB CPU | 2,128 | 9.62 | |||
db file scattered read | 4,104,747 | 721 | 0 | 3.26 | User I/O |
db file parallel read | 10,590 | 693 | 65 | 3.13 | User I/O |
read by other session 的定义如下:
read by other session Definition: When information is requested from the database, Oracle will first read the data from disk into the database buffer cache. If two or more sessions request the same information, the first session will read the data into the buffer cache while other sessions wait. In previous versions this wait was classified under the “buffer busy waits” event. However, in Oracle 10.1 and higher this wait time is now broken out into the “read by other session” wait event. Excessive waits for this event are typically due to several processes repeatedly reading the same blocks, e.g. many sessions scanning the same index or performing full-table scans on the same table. Tuning this issue is a matter of finding and eliminating this contention. Confio concludes with a summary that “read by other session waits” are very similar to buffer busy waits When a session waits on the “read by other session” event, it indicates a wait for another session to read the data from disk into the Oracle buffer cache. If this happens too often the performance of the query or the entire database can suffer. Typically this is caused by contention for “hot” blocks or objects so it is imperative to find out which data is being contended for. Once that is known this document lists several alternative methods for solving the issue. 总结:两个或者多个会话同时需要把硬盘中的对象装载到data buffer中,当其中一个会话把对象装入后,其他会话就处于read by other session等待状态;这个是oracle 10g 从oracle 9i的buffer busy waits中分离出来的,也是需要一种热块现象从上面的解释可以知道,read by other session如果伴随着db file sequential read出现,通常表示有索引热块。
导致索引热块的SQL如下:
select count(*) from p95169.order_info o where o.proxyuseruuid =:1 and proxyuseruuid is not null and proxyuseruuid <> 0 and o.ORDERSTATE in ( 0, 1, 3, 2008, 2009, 3008, 3009, 5002, 5003, 5004, 5006, 7001, 7003, 7002, 7004, 7006 ) and o.ORDERCREATEDTIME >= to_char(sysdate - 15 , ‘yyyyMMddHH24mmss‘) and o.ORDERCREATEDTIME <= to_char(sysdate , ‘yyyyMMddHH24mmss‘) and o.confirmstate in ( 1 ) and o.paystate in ( 1, 0 ) and o.CLINICALDATE <= to_char(sysdate, ‘yyyyMMDD‘) and o.sourceplatid in ( 20 )
通过分析执行计划,可知它走的是以下索引:
CREATE INDEX "P95169"."IDX_ORDER_HOS_STAT_CLINICAL" ON "P95169"."ORDER_INFO" ("CLINICALDATE" DESC, "ORDERSTATE", "HOSPITALUUID", "ORDERUUID", "RESERVETIMERANGE", "PATIENTNAME", "CONFIRMSTATE", "SOURCEPLATID", "SEEFLAG")根据索引的前缀性原则,我们可以知道,上诉索引真正用的的字段是前两列,而前两列在where字句里的过滤条件是固定不变的,如果同时又多个这样的SQL在执行,就会引起索引热块,即产生read by other session
通过观察可知,该SQL语句where字句里变化的字段是proxyuseruuid,因此重建一个索引,包含该字段,就可以避免索引热块:
CREATE INDEX "P95169"."ORDER_INFO_PROXY" ON "P95169"."ORDER_INFO" ("PROXYUSERUUID", "CLINICALDATE", "ORDERCREATEDTIME")
至此,问题解决。
参考文档:http://www.xifenfei.com/1200.html