对头,SQL的执行计划是会变。
如果没有绑定变量,那么每次执行的是不一样的SQL,SQL的执行计划会变。
如果绑定了变量,SQL执行第N次的时候,执行计划可能已经不在共享池了或者更新了表的统计信息,这种情况下会重新分析SQL,因为索引或者表的数据等之类的会有改变,所以执行计划也可能会改变。
举例说明:
//创建一个sequence
SQL> create sequence num;
Sequence created.
//建表
SQL> create table test
2 as
3 select num.nextval n,t.*
4 from dba_tables t
5 ;
Table created.
//建索引
SQL> create index ind_test on test(n);
Index created.
//收集统计信息
SQL> exec dbms_stats.gather_table_stats('sys','test');
PL/SQL procedure successfully completed.
//执行SQL查看执行计划
SQL> set autotrace traceonly;
SQL> select * from test where n=1;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1 Bytes=203
)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST' (TABLE) (Cost=2 Ca
rd=1 Bytes=203)
2 1 INDEX (RANGE SCAN) OF 'IND_TEST' (INDEX) (Cost=1 Card=1) //执行计划走的是索引
//修改表里面的数据,使索引字段所有值相同
SQL> set autotrace off
SQL> update test
2 set n=1;
1501 rows updated.
SQL> commit;
Commit complete.
//重新收集表的统计信息
SQL> exec dbms_stats.gather_table_stats('sys','test');
PL/SQL procedure successfully completed.
//执行同样的SQL
SQL> set autotrace traceonly;
SQL> select * from test where n=1;
1501 rows selected.
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=12 Card=1501 Bytes
=303202)
1 0 TABLE ACCESS (FULL) OF 'TEST' (TABLE) (Cost=12 Card=1501 B //执行计划走的是全表扫描
ytes=303202)
[本帖最后由 zhangqhs 于 2011-1-9 21:06 编辑]