• 为什么index fast full scan会扫描segment header,index full scan 不扫描 segment header


    index full scan , 扫描root block ---> branch block ----> leaf block ,扫描leaf block的时候是有序的,可以从左往右,也可以从右往左,返回的结果也是有序的,并且是但块读

    index fast full scan 扫描 索引段头(单块读) --->root block---->branch block----->leaf block

    下面来做个实验(基于Oracle10g,段自动管理)

    create table test as select * from dba_objects;

    alter table test modify owner not null;

    create index idx_owner on test(owner);

    select /*+ index(test idx_owner) */ owner from test where rownum<1001;       ----它会走 index full scan

    select /*+ index_ffs(test idx_owner) */ owner from test where rownum<1001;  ----它会走 index fast full scan

    对 index full scan 的SQL 进行10046跟踪,跟踪的时候记得设置下面参数

    set arraysize 1000;
    alter system flush buffer_cache; ----一定要刷新,不然观察不到 db file sequential read
    alter system flush shared_pool;
    alter session set events '10046 trace name context forever, level 8';

    select /*+ index(test idx_owner) */ owner from test where rownum<1001; 

    alter session set events '10046 trace name context off';

    找到10046 trace 文件

    =====================
    PARSING IN CURSOR #1 len=69 dep=0 uid=54 oct=3 lid=54 tim=271045223908 hv=4111226343 ad='1c118ecc'
    select /*+ index(test idx_owner) */ owner from test where rownum<1001
    END OF STMT
    PARSE #1:c=78001,e=192236,p=26,cr=165,cu=0,mis=1,r=0,dep=0,og=1,tim=271045223905
    EXEC #1:c=0,e=14,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=271045224086
    WAIT #1: nam='SQL*Net message to client' ela= 2 driver id=1111838976 #bytes=1 p3=0 obj#=10234 tim=271045224133
    WAIT #1: nam='db file sequential read' ela= 8887 file#=4 block#=3468 blocks=1 obj#=53777 tim=271045233777
    WAIT #1: nam='db file sequential read' ela= 277 file#=4 block#=3469 blocks=1 obj#=53777 tim=271045234190
    FETCH #1:c=0,e=10124,p=2,cr=2,cu=0,mis=0,r=1,dep=0,og=1,tim=271045234294
    WAIT #1: nam='SQL*Net message from client' ela= 324 driver id=1111838976 #bytes=1 p3=0 obj#=53777 tim=271045234689
    WAIT #1: nam='SQL*Net message to client' ela= 1 driver id=1111838976 #bytes=1 p3=0 obj#=53777 tim=271045234789
    WAIT #1: nam='SQL*Net more data to client' ela= 9 driver id=1111838976 #bytes=2002 p3=0 obj#=53777 tim=271045235017
    WAIT #1: nam='db file sequential read' ela= 286 file#=4 block#=3470 blocks=1 obj#=53777 tim=271045235371
    WAIT #1: nam='SQL*Net more data to client' ela= 9 driver id=1111838976 #bytes=2000 p3=0 obj#=53777 tim=271045235550
    WAIT #1: nam='db file sequential read' ela= 321 file#=4 block#=3471 blocks=1 obj#=53777 tim=271045235939
    FETCH #1:c=0,e=1279,p=2,cr=3,cu=0,mis=0,r=999,dep=0,og=1,tim=271045236055
    WAIT #1: nam='SQL*Net message from client' ela= 8914715 driver id=1111838976 #bytes=1 p3=0 obj#=53777 tim=271054150848
    STAT #1 id=1 cnt=1000 pid=0 pos=1 obj=0 op='COUNT STOPKEY (cr=5 pr=4 pw=0 time=10119 us)'
    STAT #1 id=2 cnt=1000 pid=1 pos=1 obj=53777 op='INDEX FULL SCAN IDX_OWNER (cr=5 pr=4 pw=0 time=10116 us)'
    =====================
    


    扫描的第一个block是3468,然后3469,3470,3471

    SQL> select header_file,header_block from dba_segments where segment_name='IDX_OWNER';

    HEADER_FILE HEADER_BLOCK
    ----------- ------------
              4         3467

    SQL> select name,height from index_stats where name='IDX_OWNER';

    NAME                               HEIGHT
    ------------------------------ ----------
    IDX_OWNER                               2      

    这个索引的段头块是3467,root block就是段头+1 ,这里 root block 就是3468 ,根据实验可知,index full scan 没有扫描 segment header ,而是直接扫描 root block

    再来看 index fast full scan 实验

    set arraysize 1000;
    alter system flush buffer_cache;
    alter system flush shared_pool;
    alter session set events '10046 trace name context forever, level 8';

    select /*+ index_ffs(test idx_owner) */ owner from test where rownum<1001;

    alter session set events '10046 trace name context off';

    找到10046 trace文件

    =====================
    PARSING IN CURSOR #4 len=73 dep=0 uid=54 oct=3 lid=54 tim=272536163194 hv=1795841612 ad='18686370'
    select /*+ index_ffs(test idx_owner) */ owner from test where rownum<1001
    END OF STMT
    PARSE #4:c=46801,e=206181,p=14,cr=55,cu=0,mis=1,r=0,dep=0,og=1,tim=272536163192
    EXEC #4:c=0,e=13,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=1,tim=272536163332
    WAIT #4: nam='SQL*Net message to client' ela= 2 driver id=1111838976 #bytes=1 p3=0 obj#=10234 tim=272536163375
    WAIT #4: nam='db file sequential read' ela= 8670 file#=4 block#=3467 blocks=1 obj#=53777 tim=272536172783
    WAIT #4: nam='db file scattered read' ela= 571 file#=4 block#=3468 blocks=5 obj#=53777 tim=272536173489
    FETCH #4:c=15600,e=10219,p=6,cr=7,cu=0,mis=0,r=1,dep=0,og=1,tim=272536173634
    WAIT #4: nam='SQL*Net message from client' ela= 255 driver id=1111838976 #bytes=1 p3=0 obj#=53777 tim=272536173968
    WAIT #4: nam='SQL*Net message to client' ela= 1 driver id=1111838976 #bytes=1 p3=0 obj#=53777 tim=272536174046
    WAIT #4: nam='SQL*Net more data to client' ela= 8 driver id=1111838976 #bytes=2002 p3=0 obj#=53777 tim=272536174209
    WAIT #4: nam='SQL*Net more data to client' ela= 6 driver id=1111838976 #bytes=2000 p3=0 obj#=53777 tim=272536174344
    FETCH #4:c=0,e=398,p=0,cr=3,cu=0,mis=0,r=999,dep=0,og=1,tim=272536174432
    *** 2012-03-02 14:25:15.649
    WAIT #4: nam='SQL*Net message from client' ela= 13715652 driver id=1111838976 #bytes=1 p3=0 obj#=53777 tim=272549890151
    STAT #4 id=1 cnt=1000 pid=0 pos=1 obj=0 op='COUNT STOPKEY (cr=10 pr=6 pw=0 time=10214 us)'
    STAT #4 id=2 cnt=1000 pid=1 pos=1 obj=53777 op='INDEX FAST FULL SCAN IDX_OWNER (cr=10 pr=6 pw=0 time=10209 us)'
    =====================


    最开始扫描的是3467,它是索引的段头,并且是单块读(注意:段头都是单块读),然后才是从3468 开始扫描,一共扫描了5个block 3468就是索引的root block

    这里也知道了,无论哪种索引扫描,都会扫描 root block

    为什么 index fast full scan 要扫描 segment header呢?因为 index fast full scan 需要扫描所有的索引块(leaf block),并且扫描不是有序的,是多块读,而且它不会回表,也就是说它不会解析出rowid,正是由于它要扫描所有的leaf block,并且是离散读,所以它必须读取segment header,不然oracle怎么知道它读取了所有的 leaf block?

    为什么 index full scan 不扫描segment header? 因为 index full scan 是连续读的,由于leaf block之间有双向指针,Oracle不需要扫描segment header就能判断 leaf block 扫描完了没,它只需要从左往右,或者从右往左一直扫描到尽头即可。

  • 相关阅读:
    PyQt作品 – PingTester – 多点Ping测试工具
    关于和技术人员交流的一二三
    Pyjamas Python Javascript Compiler, Desktop Widget Set and RIA Web Framework
    Hybrid Qt applications with PySide and Django
    pyjamas build AJAX apps in Python (like Google did for Java)
    PyQt 维基百科,自由的百科全书
    InfoQ:请问为什么仍要选择Java来处理后端的工作?
    Eric+PyQt打造完美的Python集成开发环境
    python select module select method introduce
    GUI Programming with Python: QT Edition
  • 原文地址:https://www.cnblogs.com/hehe520/p/6330551.html
Copyright © 2020-2023  润新知