|
发现oracle 9.2.0.8中cbo总是不能正确得到执行计划
Connected to:
Oracle9i Enterprise Edition Release 9.2.0.8.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.8.0 - Production
SQL> create table x1 as select * from dba_objects;
Table created.
Elapsed: 00:00:00.05
SQL> create index ind_x1 on x1 (upper(object_name));
Index created.
Elapsed: 00:00:00.02
SQL> exec dbms_stats.gather_table_stats(user,'X1',cascade=>true,method_opt=>'for all columns size 1');
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.05
SQL> set autotrace traceonly
SQL> select * from (
2 select * from x1 where upper(object_name) is not null order by upper(object_name)
3 ) where rownum <11;
10 rows selected.
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=112 Card=10 Bytes=1770)
1 0 COUNT (STOPKEY)
2 1 VIEW (Cost=112 Card=6263 Bytes=1108551)
3 2 SORT (ORDER BY STOPKEY) (Cost=112 Card=6263 Bytes=538618)
4 3 TABLE ACCESS (FULL) OF 'X1' (Cost=10 Card=6263 Bytes=538618)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
81 consistent gets
0 physical reads
0 redo size
1702 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
1 sorts (memory)
0 sorts (disk)
10 rows processed
SQL> select * from (
2 select /*+ index(x1) */* from x1 where upper(object_name) is not null order by upper(object_name)
3 ) where rownum <11;
10 rows selected.
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2273 Card=10 Bytes=1770)
1 0 COUNT (STOPKEY)
2 1 VIEW (Cost=2273 Card=6263 Bytes=1108551)
3 2 TABLE ACCESS (BY INDEX ROWID) OF 'X1' (Cost=2273 Card=6263 Bytes=538618)
4 3 INDEX (FULL SCAN) OF 'IND_X1' (NON-UNIQUE) (Cost=25 Card=6263)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
7 consistent gets
0 physical reads
0 redo size
1702 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
10 rows processed
SQL> set autotrace off
而且就算使用了index ind_x1,INDEX (FULL SCAN) OF 'IND_X1' 的card也是6263(全表的行数)~ 从逻辑读上看stop key肯定是起作用了,所以用10046看了一下
1。先做了一个treedump ind_x1
SQL> select object_id from dba_objects where object_name='IND_X1';
OBJECT_ID
----------
6549
Elapsed: 00:00:00.04
SQL> alter session set events 'immediate trace name treedump level 6549';
Session altered.
Elapsed: 00:00:00.03
--Index IND_X1 Treedump:
*** SESSION ID9.7) 2009-10-29 12:05:39.729
----- begin tree dump
branch: 0xc0264c 12592716 (0: nrow: 24, level: 1)
leaf: 0xc0264d 12592717 (-1: nrow: 243 rrow: 243)
leaf: 0xc0264e 12592718 (0: nrow: 244 rrow: 244)
leaf: 0xc0264f 12592719 (1: nrow: 262 rrow: 262)
leaf: 0xc02650 12592720 (2: nrow: 239 rrow: 239)
leaf: 0xc02651 12592721 (3: nrow: 247 rrow: 247)
leaf: 0xc02652 12592722 (4: nrow: 248 rrow: 248)
leaf: 0xc02653 12592723 (5: nrow: 252 rrow: 252)
leaf: 0xc02654 12592724 (6: nrow: 273 rrow: 273)
leaf: 0xc02655 12592725 (7: nrow: 347 rrow: 347)
leaf: 0xc02656 12592726 (8: nrow: 312 rrow: 312)
leaf: 0xc02657 12592727 (9: nrow: 253 rrow: 253)
leaf: 0xc02658 12592728 (10: nrow: 267 rrow: 267)
leaf: 0xc0265a 12592730 (11: nrow: 303 rrow: 303)
leaf: 0xc0265b 12592731 (12: nrow: 250 rrow: 250)
leaf: 0xc0265c 12592732 (13: nrow: 262 rrow: 262)
leaf: 0xc0265d 12592733 (14: nrow: 278 rrow: 278)
leaf: 0xc0265e 12592734 (15: nrow: 255 rrow: 255)
leaf: 0xc0265f 12592735 (16: nrow: 250 rrow: 250)
leaf: 0xc02660 12592736 (17: nrow: 251 rrow: 251)
leaf: 0xc02661 12592737 (18: nrow: 238 rrow: 238)
leaf: 0xc02662 12592738 (19: nrow: 255 rrow: 255)
leaf: 0xc02663 12592739 (20: nrow: 268 rrow: 268)
leaf: 0xc02664 12592740 (21: nrow: 257 rrow: 257)
leaf: 0xc02665 12592741 (22: nrow: 209 rrow: 209)
----- end tree dump
可见一个24个叶节点一个根节点~
如果stop key起作用,那么index full scan只需要读取0xc0264c (根节点)和0xc0264d (第一个叶节点)
2。用10046验证
SQL> conn / as sysdba
Connected.
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> startup
ORACLE instance started.
Total System Global Area 114367984 bytes
Fixed Size 454128 bytes
Variable Size 88080384 bytes
Database Buffers 25165824 bytes
Redo Buffers 667648 bytes
Database mounted.
Database opened.
SQL> conn mydb
Enter password:
Connected.
SQL> alter session set statistics_level = all;
Session altered.
Elapsed: 00:00:00.00
SQL> alter session set events '10046 trace name context forever, level 12';
Session altered.
Elapsed: 00:00:00.02
SQL> select * from (
2 select /*+ index(x1) */* from x1 where upper(object_name) is not null order by upper(object_name)
3 ) where rownum <11;
... ...
10 rows selected.
Elapsed: 00:00:00.03
SQL> alter session set events '10046 trace name context off';
Session altered.
Elapsed: 00:00:00.01
SQL> exit
*** 2009-10-29 15:47:58.606
*** SESSION ID9.5) 2009-10-29 15:47:58.497
APPNAME mod='SQL*Plus' mh=3669949024 act='' ah=4029777240
=====================
PARSING IN CURSOR #1 len=69 dep=0 uid=24 oct=42 lid=24 tim=7232137429 hv=2004533713 ad='67998474'
alter session set events '10046 trace name context forever, level 12'
END OF STMT
EXEC #1:c=0,e=64,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=4,tim=7231998352
WAIT #1: nam='SQL*Net message to client' ela= 4 p1=1111838976 p2=1 p3=0
WAIT #1: nam='SQL*Net message from client' ela= 1601545 p1=1111838976 p2=1 p3=0
=====================
PARSING IN CURSOR #1 len=132 dep=0 uid=24 oct=3 lid=24 tim=7233790753 hv=2342456978 ad='679c28d4'
select * from (
select /*+ index(x1) */* from x1 where upper(object_name) is not null order by upper(object_name)
) where rownum <11
END OF STMT
PARSE #1:c=0,e=1805,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=4,tim=7233790750
BINDS #1:
EXEC #1:c=0,e=407,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=7233850195
WAIT #1: nam='SQL*Net message to client' ela= 4 p1=1111838976 p2=1 p3=0
WAIT #1: nam='db file sequential read' ela= 20669 p1=3 p2=9804 p3=1
WAIT #1: nam='db file sequential read' ela= 157 p1=3 p2=9805 p3=1
WAIT #1: nam='db file sequential read' ela= 1020 p1=3 p2=9797 p3=1
FETCH #1:c=0,e=57818,p=3,cr=3,cu=0,mis=0,r=1,dep=0,og=4,tim=7233925450
WAIT #1: nam='SQL*Net message from client' ela= 335 p1=1111838976 p2=1 p3=0
WAIT #1: nam='SQL*Net message to client' ela= 1 p1=1111838976 p2=1 p3=0
WAIT #1: nam='db file sequential read' ela= 22130 p1=3 p2=5220 p3=1
WAIT #1: nam='db file sequential read' ela= 20614 p1=3 p2=9767 p3=1
FETCH #1:c=0,e=76821,p=2,cr=4,cu=0,mis=0,r=9,dep=0,og=4,tim=7234033444
WAIT #1: nam='SQL*Net message from client' ela= 896671 p1=1111838976 p2=1 p3=0
STAT #1 id=1 cnt=10 pid=0 pos=1 obj=0 op='COUNT STOPKEY (cr=7 r=5 w=0 time=134324 us)'
STAT #1 id=2 cnt=10 pid=1 pos=1 obj=0 op='VIEW (cr=7 r=5 w=0 time=134304 us)'
=====================
PARSING IN CURSOR #2 len=116 dep=1 uid=0 oct=3 lid=0 tim=7234985213 hv=431456802 ad='67b8b790'
select o.owner#,o.name,o.namespace,o.remoteowner,o.linkname,o.subname,o.dataobj#,o.flags from obj$ o where o.obj#=:1
END OF STMT
PARSE #2:c=0,e=981,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=0,tim=7234985209
BINDS #2:
bind 0: dty=2 mxl=22(22) mal=00 scl=00 pre=00 oacflg=08 oacfl2=1 size=24 offset=0
bfp=051ccc5c bln=22 avl=03 flg=05
value=6548
EXEC #2:c=0,e=19735,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=7235043031
FETCH #2:c=0,e=38,p=0,cr=3,cu=0,mis=0,r=1,dep=1,og=4,tim=7235043338
STAT #1 id=3 cnt=10 pid=2 pos=1 obj=6548 op='TABLE ACCESS BY INDEX ROWID X1 (cr=7 r=5 w=0 time=134286 us)'
STAT #1 id=4 cnt=10 pid=3 pos=1 obj=6549 op='INDEX FULL SCAN IND_X1 (cr=3 r=2 w=0 time=27219 us)'
=====================
PARSING IN CURSOR #1 len=55 dep=0 uid=24 oct=42 lid=24 tim=7235069076 hv=4110456808 ad='6798b574'
alter session set events '10046 trace name context off'
END OF STMT
PARSE #1:c=0,e=282,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=4,tim=7235069072
BINDS #1:
EXEC #1:c=0,e=19465,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=7235113364
可见只访问了5个块~
file#=3 block#=9804,9805,9797,5220,9767
SQL> select file#,rfile# from v$datafile where file#=3;
FILE# RFILE#
---------- ----------
3 3
其中9797 5220 9767应该是'TABLE ACCESS BY INDEX ROWID X1'产生的
SQL> select rowid,dbms_rowid.ROWID_RELATIVE_FNO(rowid),dbms_rowid.ROWID_BLOCK_NUMBER(rowid) from (
2 select /*+ index(x1) */* from x1 where upper(object_name) is not null order by upper(object_name)
3 ) where rownum <11;
ROWID DBMS_ROWID.ROWID_RELATIVE_FNO(ROWID) DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID)
------------------ ------------------------------------ ------------------------------------
AAABmUAADAAACZFAAE 3 9797
AAABmUAADAAACZFAAF 3 9797
AAABmUAADAAACZFAAi 3 9797
AAABmUAADAAACZFAAG 3 9797
AAABmUAADAAACZFAAH 3 9797
AAABmUAADAAABRkAAA 3 5220
AAABmUAADAAABRkAAB 3 5220
AAABmUAADAAABRkAAC 3 5220
AAABmUAADAAABRkAAD 3 5220
AAABmUAADAAACYnAAQ 3 9767
而9804,9805转换成rdba就是C0264C,C0264D,也就是ind_x1的根节点和叶节点~
但是忽然看到
STAT #1 id=3 cnt=10 pid=2 pos=1 obj=6548 op='TABLE ACCESS BY INDEX ROWID X1 (cr=7 r=5 w=0 time=134286 us)'
STAT #1 id=4 cnt=10 pid=3 pos=1 obj=6549 op='INDEX FULL SCAN IND_X1 (cr=3 r=2 w=0 time=27219 us)'
也就是说index full scan产生了3个逻辑读cr=3;'TABLE ACCESS BY INDEX ROWID产生了4个逻辑读cr=7
想要看看逻辑读到到底是从哪里来的
记得有人说过
consistent gets = rownum / fetch array size + used datablock
SQL> show array
arraysize 15
我的fetch array是15
那么从索引中找到10行数据需要的逻辑读就是
CEIL(10/15)+2=3
返回表取出10行数据需要的逻辑读
CEIL(10/15)+3=4
似乎很正确~
于是想用Huang版提到的10202 event确认一下
10202event的含义是Consistent read block header
SQL> alter session set events '10202 trace name context forever';
Session altered.
Elapsed: 00:00:00.00
SQL> select * from (
2 select /*+ index(x1) */* from x1 where upper(object_name) is not null order by upper(object_name)
3 ) where rownum <11;
... ...
10 rows selected.
Elapsed: 00:00:00.07
SQL> alter session set events '10202 trace name context off';
Session altered.
Elapsed: 00:00:00.00
然后看trace,结果问题来了....
--10202 (Consistent read block header) Trace:
*** 2009-10-29 12:07:26.066
Consistent read complete...
Block header dump: 0x00c0264d --第一个叶节点~
Object id on Block? Y
seg/obj: 0x1995 csc: 0x00.179da7 itc: 2 flg: E typ: 2 - INDEX
brn: 0 bdba: 0xc02649 ver: 0x01
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x02 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.00179da7
Consistent read complete...
Block header dump: 0x00c02645
Object id on Block? Y
seg/obj: 0x1994 csc: 0x00.179d72 itc: 3 flg: E typ: 1 - DATA
brn: 0 bdba: 0xc02641 ver: 0x01
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.00179d72
0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x03 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
Consistent read complete...
Block header dump: 0x00c0264d --第一个叶节点
Object id on Block? Y
seg/obj: 0x1995 csc: 0x00.179da7 itc: 2 flg: E typ: 2 - INDEX
brn: 0 bdba: 0xc02649 ver: 0x01
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x02 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.00179da7
Consistent read complete...
Block header dump: 0x00c02645
Object id on Block? Y
seg/obj: 0x1994 csc: 0x00.179d72 itc: 3 flg: E typ: 1 - DATA
brn: 0 bdba: 0xc02641 ver: 0x01
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.00179d72
0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x03 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
Consistent read complete...
Block header dump: 0x00c01464
Object id on Block? Y
seg/obj: 0x1994 csc: 0x00.179d72 itc: 3 flg: E typ: 1 - DATA
brn: 0 bdba: 0xc01461 ver: 0x01
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.00179d72
0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x03 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
Consistent read complete...
Block header dump: 0x00c02627
Object id on Block? Y
seg/obj: 0x1994 csc: 0x00.179d72 itc: 3 flg: E typ: 1 - DATA
brn: 0 bdba: 0xc02621 ver: 0x01
inc: 0 exflg: 0
Itl Xid Uba Flag Lck Scn/Fsc
0x01 0xffff.000.00000000 0x00000000.0000.00 C--- 0 scn 0x0000.00179d72
0x02 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
0x03 0x0000.000.00000000 0x00000000.0000.00 ---- 0 fsc 0x0000.00000000
SQL> select DBMS_UTILITY.data_block_address_file(TO_NUMBER(LTRIM('0x00c02645',
2 '0x'),
3 'xxxxxxxx')) rfile#,
4 DBMS_UTILITY.data_block_address_block(TO_NUMBER(LTRIM('0x00c02645',
5 '0x'),
6 'xxxxxxxx')) block#
7 from dual
8 /
RFILE# BLOCK#
---------- ----------
3 9797
Elapsed: 00:00:00.00
SQL> ed
Wrote file afiedt.buf
1 select DBMS_UTILITY.data_block_address_file(TO_NUMBER(LTRIM('0x00c01464',
2 '0x'),
3 'xxxxxxxx')) rfile#,
4 DBMS_UTILITY.data_block_address_block(TO_NUMBER(LTRIM('0x00c01464',
5 '0x'),
6 'xxxxxxxx')) block#
7* from dual
SQL> /
RFILE# BLOCK#
---------- ----------
3 5220
Elapsed: 00:00:00.00
SQL> ed
Wrote file afiedt.buf
1 select DBMS_UTILITY.data_block_address_file(TO_NUMBER(LTRIM('0x00c02627',
2 '0x'),
3 'xxxxxxxx')) rfile#,
4 DBMS_UTILITY.data_block_address_block(TO_NUMBER(LTRIM('0x00c02627',
5 '0x'),
6 'xxxxxxxx')) block#
7* from dual
SQL> /
RFILE# BLOCK#
---------- ----------
3 9767
Elapsed: 00:00:00.00
从trace上来看
并没有读根节点
1。第一个枝节点
2。table block#9797
3。第一个枝节点
4。table block#9797
5。table block#5220
6。table block#9767
从总数上看,才6个~ 明显不对呀~ 请问一下这是为什么? |
|