zoukankan      html  css  js  c++  java
  • 为什么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 扫描完了没,它只需要从左往右,或者从右往左一直扫描到尽头即可。

  • 相关阅读:
    Raspberrypi安装使用开发简要说明
    android UI之Shape详解_GradientDrawable
    智能电视前传——盒子
    Winform不用窗体之间传值
    uva 10706 Number Sequence(数学规律)
    动态规划——矩阵链相乘
    SQL Server 锁
    Azure 配置高可用的准备系列工作-建立不同区域的存储账户和建立网络!
    仿小米简约Calculator
    CentOS 中使用yum出现的“UnicodeDecodeError: &#39;ascii&#39; codec”问题解决方法
  • 原文地址:https://www.cnblogs.com/hehe520/p/6330551.html
Copyright © 2011-2022 走看看