在Oracle9i中使用DBMS_STATS.DELETE_INDEX_STATS删除索引的统计后不能立刻对执行计划产生影响 (1)在scott.dept表的dname列有索引IDX_DEPT_DNAME,但没有对其进行分析统计 CREATE INDEX SCOTT.IDX_DEPT_DNAME ON SCOTT.DEPT (DNAME) TABLESPACE users; ORA9I> select BLEVEL,DISTINCT_KEYS,LAST_ANALYZED 2 from dba_indexes where INDEX_NAME='IDX_DEPT_DNAME'; BLEVEL DISTINCT_KEYS LAST_ANAL ---------- ------------- --------- ORA9I> SET AUTOTRACE TRACEONLY EXP ORA9I> select * from scott.dept where dname='ACCOUNTING'; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE (Cost=2 Card=2 Bytes=40) 1 0 TABLE ACCESS (FULL) OF 'DEPT' (Cost=2 Card=2 Bytes=40) 此时,该查询没有使用IDX_DEPT_DNAME索引 (2)分析索引 ORA9I> BEGIN 2 SYS.DBMS_STATS.GATHER_INDEX_STATS ( 3 OwnName => 'SCOTT' ,IndName => 'IDX_DEPT_DNAME' ); 4 END; 5 / PL/SQL procedure successfully completed. ORA9I> SET AUTOTRACE OFF ORA9I> select BLEVEL,DISTINCT_KEYS,LAST_ANALYZED 2 from dba_indexes where INDEX_NAME='IDX_DEPT_DNAME'; BLEVEL DISTINCT_KEYS LAST_ANAL ---------- ------------- --------- 0 4 15-JUN-05 ORA9I> SET AUTOTRACE TRACEONLY EXP ORA9I> select * from scott.dept where dname='ACCOUNTING'; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE (Cost=2 Card=2 Bytes=40) 1 0 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT' (Cost=2 Card=2 Byt es=40) 2 1 INDEX (RANGE SCAN) OF 'IDX_DEPT_DNAME' (NON-UNIQUE) (Cos t=1 Card=2) 此时,该查询使用IDX_DEPT_DNAME索引 (3)使用SYS.DBMS_STATS.DELETE_INDEX_STATS删除统计值 ORA9I> BEGIN 2 SYS.DBMS_STATS.DELETE_INDEX_STATS ( 3 OwnName => 'SCOTT' ,IndName => 'IDX_DEPT_DNAME'); 4 END; 5 / PL/SQL procedure successfully completed. ORA9I> select * from scott.dept where dname='ACCOUNTING'; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE (Cost=2 Card=2 Bytes=40) 1 0 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT' (Cost=2 Card=2 Byt es=40) 2 1 INDEX (RANGE SCAN) OF 'IDX_DEPT_DNAME' (NON-UNIQUE) (Cos t=1 Card=2) ORA9I> SET AUTOTRACE OFF ORA9I> select BLEVEL,DISTINCT_KEYS,LAST_ANALYZED 2 from dba_indexes where INDEX_NAME='IDX_DEPT_DNAME'; BLEVEL DISTINCT_KEYS LAST_ANAL ---------- ------------- --------- 此时,统计值虽然已经没有,但查询仍然使用IDX_DEPT_DNAME索引,分析可能的原因是shard pool中的字典信息(data dictionary cache)没有更新 (4)清空shared pool ORA9I> ALTER SYSTEM FLUSH SHARED_POOL; System altered. ORA9I> SET AUTOTRACE TRACEONLY EXP ORA9I> select * from scott.dept where dname='ACCOUNTING'; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE (Cost=2 Card=2 Bytes=40) 1 0 TABLE ACCESS (FULL) OF 'DEPT' (Cost=2 Card=2 Bytes=40) shared pool清空后,执行计划改变,不再使用索引 (5)使用Analyze命令删除索引统计值 ORA9I> BEGIN 2 SYS.DBMS_STATS.GATHER_INDEX_STATS ( 3 OwnName => 'SCOTT' ,IndName => 'IDX_DEPT_DNAME' ); 4 END; 5 / PL/SQL procedure successfully completed. ORA9I> SET AUTOTRACE OFF ORA9I> select BLEVEL,DISTINCT_KEYS,LAST_ANALYZED 2 from dba_indexes where INDEX_NAME='IDX_DEPT_DNAME'; BLEVEL DISTINCT_KEYS LAST_ANAL ---------- ------------- --------- 0 4 15-JUN-05 ORA9I> SET AUTOTRACE TRACEONLY EXP ORA9I> select * from scott.dept where dname='ACCOUNTING'; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE (Cost=2 Card=2 Bytes=40) 1 0 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT' (Cost=2 Card=2 Byt es=40) 2 1 INDEX (RANGE SCAN) OF 'IDX_DEPT_DNAME' (NON-UNIQUE) (Cos t=1 Card=2) ORA9I> Analyze Index SCOTT.IDX_DEPT_DNAME 2 Delete Statistics; Index analyzed. ORA9I> select * from scott.dept where dname='ACCOUNTING'; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=CHOOSE (Cost=2 Card=2 Bytes=40) 1 0 TABLE ACCESS (FULL) OF 'DEPT' (Cost=2 Card=2 Bytes=40) ORA9I> SET AUTOTRACE OFF ORA9I> select BLEVEL,DISTINCT_KEYS,LAST_ANALYZED 2 from dba_indexes where INDEX_NAME='IDX_DEPT_DNAME'; BLEVEL DISTINCT_KEYS LAST_ANAL ---------- ------------- --------- 可见,使用Analyze删除索引统计值后,字典缓冲中的数据也被更新,执行计划立刻改变 (5)在10g(10.1.0.3.0 )中 CREATE INDEX SCOTT.IDX_DEPT_DNAME ON SCOTT.DEPT (DNAME) TABLESPACE users; ORA10G> set autotrace off ORA10G> select BLEVEL,DISTINCT_KEYS,LAST_ANALYZED 2 from dba_indexes where INDEX_NAME='IDX_DEPT_DNAME'; BLEVEL DISTINCT_KEYS LAST_ANAL ---------- ------------- --------- ORA10G> set autotrace traceonly exp ORA10G> select * from scott.dept where dname='ACCOUNTING'; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=ALL_ROWS (Cost=3 Card=1 Bytes=20) 1 0 TABLE ACCESS (FULL) OF 'DEPT' (TABLE) (Cost=3 Card=1 Bytes =20) ORA10G> BEGIN 2 SYS.DBMS_STATS.GATHER_INDEX_STATS ( 3 OwnName => 'SCOTT' ,IndName => 'IDX_DEPT_DNAME' ); 4 END; 5 / PL/SQL procedure successfully completed. ORA10G> select * from scott.dept where dname='ACCOUNTING'; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=ALL_ROWS (Cost=2 Card=1 Bytes=20) 1 0 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT' (TABLE) (Cost=2 Ca rd=1 Bytes=20) 2 1 INDEX (RANGE SCAN) OF 'IDX_DEPT_DNAME' (INDEX) (Cost=1 C ard=1) ORA10G> BEGIN 2 SYS.DBMS_STATS.DELETE_INDEX_STATS ( 3 OwnName => 'SCOTT' ,IndName => 'IDX_DEPT_DNAME'); 4 END; 5 / PL/SQL procedure successfully completed. ORA10G> select * from scott.dept where dname='ACCOUNTING'; Execution Plan ---------------------------------------------------------- 0 SELECT STATEMENT ptimizer=ALL_ROWS (Cost=3 Card=1 Bytes=20) 1 0 TABLE ACCESS (FULL) OF 'DEPT' (TABLE) (Cost=3 Card=1 Bytes =20) 可见,在Oracle10g中,已解决了上述问题,通过DBMS_STATS.DELETE_INDEX_STATS删除索引统计值后,shared pool中的数据字典信息被刷新,相关的执行计划会立即改变。 |