• Oracle读取事件的命名理由(哈哈)


    又给大家弄来一篇好文章,现在对oracle的慢慢起了前所未有的feel,也希望自己一直能这样努力下去,看起这些expert写的文章也没有原来那种比较吃力的感觉,一切都在进入正轨。

    db file sequential read与db file scattered read这两个等待事件在今天又让我们重温了一下2年前的一次争论, 大家对于这两个事件以及其名称的理解进行了多个角度的解读, 我觉得我有责任将Jeff Holt在多年前的这篇旧文翻译出来, 以助后来者理解这两个让人迷惑的概念. 翻译的比较仓促, 不足之处尽情谅解
    
    本文的原文链接: Why are Oracle’s Read Events Named Backwards?
    原文版权归Jeff Holt以及Hotsos公司所有.

    为什么Oracle的读取事件使用”向后兼容的命名方式”?
    By Jeff Holt Translated by Jametong

    在几乎所有的Oracle跟踪文件中,都有两个出现频繁的事件:db file sequential readdb file scattered read.这些事件表明Oracle内核请求从磁盘读取数据块.

    当我们想到磁盘时,我们熟悉的顺序访问(sequential read)的概念是,一个进程从磁盘读取大块的连续数据.当Oracle执行一次全表扫描时,会在一次大I/O中读取多个Oracle数据块的数据,它是一次顺序读取.当然,在我们想到磁盘时,也会习惯于随机访问(random access)这个概念. 在一个有合理设计的索引的查询中,SQL 语句通常会使用随机访问来完成单块读取(single block read)调用.

    然而,如果你曾经读过任何关于Oracle等待事件的内容,都会发现db file sequential read是用来表示随机读取(例如,索引扫描),db file scattered read是用来表示顺序读取(例如,全表扫描). Oracle使用这个术语表示确实不是很直观. 这使得部分猜测Oracle的事件命名是一种不经意的向后兼容命名. 嗯,这个理论很有意思,不过事实不是这样. 这些事件之所以如此命名确实有个很好的理由.

    事件名db file sequential read与db file scattered read描述的是如何将数据块存储到内存中的,而不是如何从磁盘进行读取. Oracle对这两个事件的命名类似于Unix对两类读取调用的命名,函数read()与readv()是其中的代表. Unix的read()函数读取文件中的一段连续的内容,并将数据的不同片段存储到不同的内存区域,此区域由一个内存应用数组所支配. 由类似于read()调用执行的Oracle磁盘读被记录为db file sequential read事件,由类似于readv()调用执行的磁盘读被记录为db file scattered read 事件.

    如果填充磁盘读取的内容的内存是连续的,发生的磁盘读就是db file sequential read.

    • Oracle 为所有的单块读取生成db file sequential read事件.Oracle始终将单个数据块存储在单个缓存缓冲块(cache buffer)中,因此单块读取永远不会产生db file scattered read事件.
    • 在Oracle 7.3以及后期版本中,当一个独占进程从磁盘中读取临时段时,Oracle会产生多块(multi-block) db file sequential read事件. Oracle早期版本会使用db file scattered read读取临时段的数据到数据库的高速缓冲池. 更新的版本发现临时段的数据几乎无法被共享或被重新访问到,因此就将其直接读取到服务器进程的程序全局区(PGA, Program Global Area)中了.

    当填充从磁盘读取的数据的内存的连续性无法被保证的时候,发生的磁盘读就是db file scattered read. 为了填充一次read()调用读取的数据,Oracle内核可能要花费更多的时间来寻找一组连续的内存.只有当read()调用于readv()调用相对readv()调用的速度优势足够抵消这部分额外的时间消耗时,使用这种方式才会有净收益. 找到连续缓冲块(buffer)的代价可能远远超过read()调用相对于readv()调用带来的好处,推动Oracle的内核开发者选择了他们现在使用的这种算法.

    • 在大部分情况下,全表扫描与快速全索引扫描都会产生一次或多次db file scattered read. 不过,有时,这些扫描只会产生db file sequential read.

    例如: 从一个Oracle跟踪文件摘录的如下片段显示,一个全表扫描仅仅使用到了db file sequential read. 这个表存储在文件2的块2到20的连续块中,它的高水位线在第16个块上. 数据库的块大小(block size)是8KB. 由于在此查询执行之前,所有的偶数块都已经存在于数据库高速缓冲池(buffer cache)中,这次扫描的读操作全都是单块读取.

    PARSING IN CURSOR #1 len=31 dep=0 uid=18 oct=3 lid=18 tim=26532087 hv=2854987545 ad='82061e04'
    select count(1) from test_tab
    END OF STMT
    PARSE #1:c=0,e=0,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=4,tim=26532087
    EXEC #1:c=0,e=0,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=26532087
    WAIT #1: nam='db file sequential read' ela= 0 p1=2 p2=3 p3=1
    WAIT #1: nam='db file sequential read' ela= 0 p1=2 p2=5 p3=1
    WAIT #1: nam='db file sequential read' ela= 0 p1=2 p2=7 p3=1
    WAIT #1: nam='db file sequential read' ela= 0 p1=2 p2=9 p3=1
    WAIT #1: nam='db file sequential read' ela= 0 p1=2 p2=11 p3=1
    WAIT #1: nam='db file sequential read' ela= 0 p1=2 p2=13 p3=1
    WAIT #1: nam='db file sequential read' ela= 0 p1=2 p2=15 p3=1
    FETCH #1:c=1,e=1,p=7,cr=14,cu=3,mis=0,r=1,dep=0,og=4,tim=26532088

    下面这些来自Solaris truss命令的输出结果展示了这个查询执行的系统调用.第23行到27行展示了文件是如何打开,以及如何以文件句柄409进行引用的.第31行显示了一次pread()系统函数的调用,除了不会与read()一样移动文件指针外,pread()的行为与read()完全一致,它接收文件偏移量作为它的第四个参数.它的返回值是成功读取的字节的大小. 由于timed_statistices实例参数为true, times()调用提供了计时信息.

    *** SUID: ruid/euid/suid = 4076 / 108 / 108 ***
    read(10, 0x010ACACE, 2064)    (sleeping...)
    read(10, "\097\0\006\0\0\0\0\003 ^".., 2064) = 151
    times(0xEFFFE360)    = 162380015
    times(0xEFFFDA80)    = 162380015
    times(0xEFFFD9C0)    = 162380015
    times(0xEFFFD9C0)    = 162380015
    time()    = 948902570
    brk(0x010E9A60)    = 0
    brk(0x010EBA60)    = 0
    brk(0x010EBA60)    = 0
    brk(0x010EDA60)    = 0
    times(0xEFFFD9C0)    = 162380015
    times(0xEFFFD9C0)    = 162380015
    times(0xEFFFC4A0)    = 162380015
    times(0xEFFFC4A0)    = 162380015
    time()    = 948902570
    times(0xEFFFD7A8)    = 162380015
    times(0xEFFFD760)    = 162380015
    times(0xEFFFC5D8)    = 162380015
    times(0xEFFFC578)    = 162380015
    times(0xEFFFBE90)    = 162380015
    open64("/home/jeffh/test/data/tools01.dbf", O_RDWR|O_DSYNC) = 15
    getrlimit(RLIMIT_NOFILE, 0xEFFFBE98)    = 0
    fstat64(409, 0xEFFFBE00)    Err#9 EBADF
    fcntl(15, F_DUP2FD, 0x00000199)    = 409
    close(15)    = 0
    fcntl(409, F_SETFD, 0x00000001)    = 0
    ioctl(409, 0x0403, 0xEFFFBE5C)    Err#25 ENOTTY
    times(0xEFFFBE48)    = 162380016
    pread(409, "0602\0\0\080\003\0\0 + B".., 8192, 24576) = 8192
    times(0xEFFFC530)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC578)    = 162380016
    pread(409, "0602\0\0\080\005\0\0 + V".., 8192, 40960) = 8192
    times(0xEFFFC530)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC578)    = 162380016
    pread(409, "0602\0\0\080\007\0\0 + V".., 8192, 57344) = 8192
    times(0xEFFFC530)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC578)    = 162380016
    pread(409, "0602\0\0\080\0\t\0\0 + V".., 8192, 73728) = 8192
    times(0xEFFFC530)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC578)    = 162380016
    pread(409, "0602\0\0\080\0\v\0\0 + V".., 8192, 90112) = 8192
    times(0xEFFFC530)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC578)    = 162380016
    pread(409, "0602\0\0\080\0\r\0\0 + V".., 8192, 106496) = 8192
    times(0xEFFFC530)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380016
    times(0xEFFFC5D8)    = 162380017
    times(0xEFFFC578)    = 162380017
    pread(409, "0602\0\0\080\00F\0\0 + V".., 8192, 122880) = 8192
    times(0xEFFFC530)    = 162380017
    times(0xEFFFC5D8)    = 162380017
    times(0xEFFFC5D8)    = 162380017
    times(0xEFFFDB40)    = 162380017
    times(0xEFFFE3A8)    = 162380017
    write(13, "\0B0\0\006\0\0\0\0\010\0".., 176) = 176
    read(10, "\0 y\0\006\0\0\0\0\003 ^".., 2064) = 121
    times(0xEFFFE360)    = 162380017
    times(0xEFFFDA80)    = 162380017
    times(0xEFFFDB40)    = 162380017
    times(0xEFFFE3A8)    = 162380017
    times(0xEFFFE360)    = 162380017
    lseek(14, 37376, SEEK_SET)    = 37376
    read(14, "\0\v04E2\0\0\0 J04E3\0\0".., 512) = 512
    times(0xEFFFE3A8)    = 162380017
    write(13, "\0 U\0\006\0\0\0\0\004\0".., 85) = 85
    read(10, 0x010ACACE, 2064)    (sleeping...)

    下表描述了Oracle产生db file sequential readdb file scattered read事件的相关情况.

    Oracle 事件产生单块读取事件的操作(p3=1)产生多块读取事件的操作(p3>1)
    db file sequential read 索引扫描,
    在区间内跳过块进行读取的全表扫描, 
    根据rowid进行的表访问等
    临时段读取
    db file scattered read 绝对不会 全表扫描,快速全索引扫描等.

    引用:
    HOLT, JEFF. 2000. “Predicting Multi-Block Read Call Sizes,” Hotsos Journal, (Jan. 2000): 8–9. http://www.hotsos.com.

    Jeff Holt是位于得克萨斯州盐湖城的Hotsos LLC公司的一位系统性能优化专家.

    No related posts.

    引自:http://www.dbthink.com/archives/468

  • 相关阅读:
    beautifulsoup的一些使用
    requests(爬虫常用)库的使用
    find a maximum product triplet in this array
    Minimum difference between two arrays
    [LeetCode] Binary Tree Upside Down
    n 刀切多少块pizza
    Biased Random Number Generator
    linked list焦点问题,面经里很多,考虑相交不相交,有环无环 + Find Leaves of Binary Tree (Java)
    replace string use another
    Union and Intersection of two sorted list
  • 原文地址:https://www.cnblogs.com/taowang2016/p/3126807.html
Copyright © 2020-2023  润新知