なぜ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
 
以下で実験を行います。(Oracle 10 gに基づいて、セグメント自動管理)
create table test as select*from dbaobject;
alter table test modify owner not null;
create index idx_owner on test(owner);
 
select/*+index(test idxuowner)*/owner from test where rownum<1001;       ----それはindex full scanを歩くことができます。
select/*+index_ffs(test idxConner)*/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 flaush shred_は観測されません。poolalter session set events'10046 trace name context forever、level 8'
select/*+index(test idxuowner)*/owner from test where rownum<1001; 
alter session set events'10046 trace name context off'
10046トラックファイルを見つけました。
=====================
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)'
=====================
スキャンの最初のブロックは3468で、次いで3469,3470,3471である。
SQL>select header_file,header_block from dba_segments where segment uname='IDX_OWNER;
HEADER_FILE HEADER_BLOCK--------------          4         3467
SQL>select name,height from index_stats where name='IDX_OWNER;
NAME                               HEIGHHT--------------IDX_OWNER                               2      
 
このインデックスのセグメントの最初のブロックは3467で、root blockはセグメントの頭+1です。ここでroot blockは3468です。実験によって、index full scanはsegment headerをスキャンしていません。直接root blockをスキャンします。
 
またindex fast full scanの実験を見にきます。
set arraysize 1000alter system flush buffer_cache;alter system fush shared upoolalter session set events'10046 trace name context forever、level 8'
select/*+index_ffs(test idxConner)*/owner from test where rownum<1001;
alter session set events'10046 trace name context off'
10046トラックファイルを見つけました。
=====================
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つのブロック3468をスキャンしました。インデックスのroot blockです。
ここでも分かりました。どのインデックスをスキャンしても、root blockをスキャンします。
 
なぜindex fast full scanはsegment headerをスキャンしますか?index fast full scanはすべてのインデックスブロックをスキャンしなければならないので、スキャンは整然としていません。複数のブロックで読んでいます。そして、表に戻らないです。つまり、rowidは解析できません。すべてのleaf blockをスキャンして離散的に読むから、segment headerを読まなければなりません。
 
なぜindex full scanはsegment headerをスキャンしないですか?index full scanは連続して読んだので、leaf blockの間に双方向のポインタがあるので、Oracleはsegment headerをスキャンする必要がなくて、leaf blockスキャンが終わったかどうかを判断できます。左から右へ、または右から左へとまっすぐにスキャンしてください。