Oracle读取事件的命名理由
db file sequential read与db file scatteredread这两个等待事件在今天又让我们重温了一下2年前的一次争论, 大家对于这两个事件以及其名称的理解进行了多个角度的解读,我觉得我有责任将Jeff Holt在多年前的这篇旧文翻译出来, 以助后来者理解这两个让人迷惑的概念. 翻译的比较仓促,不足之处尽情谅解
本文的原文链接:
原文版权归Jeff Holt以及Hotsos公司所有.
为什么Oracle的读取事件使用”向后兼容的命名方式”?
By
在几乎所有的Oracle跟踪文件中,都有两个出现频繁的事件:db file sequentialread与db file scatteredread.这些事件表明Oracle内核请求从磁盘读取数据块.
当我们想到磁盘时,我们熟悉的顺序访问(sequentialread)的概念是,一个进程从磁盘读取大块的连续数据.当Oracle执行一次全表扫描时,会在一次大I/O中读取多个Oracle数据块的数据,它是一次顺序读取.当然,在我们想到磁盘时,也会习惯于随机访问(randomaccess)这个概念. 在一个有合理设计的索引的查询中,SQL 语句通常会使用随机访问来完成单块读取(singleblock read)调用.
然而,如果你曾经读过任何关于Oracle等待事件的内容,都会发现db file sequentialread是用来表示随机读取(例如,索引扫描),db file scatteredread是用来表示顺序读取(例如,全表扫描). Oracle使用这个术语表示确实不是很直观.这使得部分猜测Oracle的事件命名是一种不经意的向后兼容命名. 嗯,这个理论很有意思,不过事实不是这样.这些事件之所以如此命名确实有个很好的理由.
事件名db file sequential read与db file scatteredread描述的是如何将数据块存储到内存中的,而不是如何从磁盘进行读取.Oracle对这两个事件的命名类似于Unix对两类读取调用的命名,函数read()与readv()是其中的代表.Unix的read()函数读取文件中的一段连续的内容,并将数据的不同片段存储到不同的内存区域,此区域由一个内存应用数组所支配.由类似于read()调用执行的Oracle磁盘读被记录为dbfile sequential read事件,由类似于readv()调用执行的磁盘读被记录为dbfile scattered read
如果填充磁盘读取的内容的内存是连续的,发生的磁盘读就是db file sequentialread.
- Oracle 为所有的单块读取生成db file sequentialread事件.Oracle始终将单个数据块存储在单个缓存缓冲块(cachebuffer)中,因此单块读取永远不会产生db file scattered read事件.
- 在Oracle7.3以及后期版本中,当一个独占进程从磁盘中读取临时段时,Oracle会产生多块(multi-block)
dbfile sequential read事件. Oracle早期版本会使用db file scatteredread读取临时段的数据到数据库的高速缓冲池.更新的版本发现临时段的数据几乎无法被共享或被重新访问到,因此就将其直接读取到服务器进程的程序全局区(PGA, ProgramGlobal Area)中了.
当填充从磁盘读取的数据的内存的连续性无法被保证的时候,发生的磁盘读就是db file scatteredread.
- 在大部分情况下,全表扫描与快速全索引扫描都会产生一次或多次db file scattered read.不过,有时,这些扫描只会产生db file sequential read.
例如:
下面这些来自Solaris
Oracle 事件 | 产生单块读取事件的操作(p3=1) | 产生多块读取事件的操作(p3>1) |
---|---|---|
db file sequential read | 索引扫描, 在区间内跳过块进行读取的全表扫描, 根据rowid进行的表访问等 | 临时段读取 |
db file scattered read | 绝对不会 | 全表扫描,快速全索引扫描等. |
引用:
HOLT, JEFF. 2000. “Predicting Multi-Block Read Call Sizes,” HotsosJournal, (Jan. 2000): 8–9.
Jeff Holt是位于得克萨斯州盐湖城的Hotsos LLC公司的一位系统性能优化专家.
No related posts.
到了Exadata时代,Oracle也与日俱进,变得容易理解多了,分别有下面三个事件,意义就一目了然了
cellsmart table scan
cellmultiblock physical read
cellsingle block physical read
dbfile sequential read:
use
Parameters:
P1 = file#
P2 = block#
P3 = blocks
file#
block#
blocks
To find the object that Oracle doing the I/O use one of the two following waysSELECT owner, segment_type, segment_name, partition_name, tablespace_name FROM dba_extents WHERE :P2 BETWEEN block_id AND (block_id + blocks - 1) AND file_id = :P1; Or even better SELECT a.SID, c.obj, c.FILE#, c.dbablk FROM v$session_wait a, x$bh c WHERE a.p1 = c.FILE#(+) AND a.p2 = c.dbablk(+) AND a.event = 'db file scattered read' AND a.SID = :sid_waiting;