Oracle 统计量NO_INVALIDATE参数配置(二)

2014-11-24 17:24:19 · 作者: · 浏览: 1
ect_id=1000


Plan hash value: 514881935


--------------------------------------------------------------------------------

| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Ti

--------------------------------------------------------------------------------

| 0 | SELECT STATEMENT | | | | 2 (100)|


| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 11 | 2 (0)| 00

|* 2 | INDEX RANGE SCAN | IDX_T_ID | 1 | | 1 (0)| 00

--------------------------------------------------------------------------------

Predicate Information (identified by operation id):


---------------------------------------------------


2 - access("OBJECT_ID"=1000)



19 rows selected



此时,最优的执行计划是索引路径。在shared pool中有一个父游标和子游标(version count=1),执行次数为1。


第二次执行之后,Shared Pool中有共享现象。相同的共享游标执行两次。



SQL> select sql_id, executions, version_count from v$sqlarea where sql_text like 'select /*+demo*/%';


SQL_ID EXECUTIONS VERSION_COUNT


------------- ---------- -------------


cnb0ktgvms6vq 2 1



之后,我们更新数据,修改数据分布结构。



SQL> update t set object_id=1000;


72729 rows updated



SQL> commit;


Commit complete



此时,如果执行SQL语句,我们发现依然是使用原有的索引路径。此时全部T表中object_id都是1000,走索引不是好的选择。




SQL> select /*+demo*/object_id, owner from t where object_id=1000;


已选择72729行。



统计信息


------------------------------------------


0 recursive calls


0 db block gets


11157 consistent gets


0 physical reads



72729 rows processed



SQL> select sql_id, executions, version_count from v$sqlarea where sql_text like 'select /*+demo*/%';

SQL_ID EXECUTIONS VERSION_COUNT


------------- ---------- -------------


cnb0ktgvms6vq 3 1



此时的路径依然是Index Range Scan。这个明显是由于统计量的过时,外加游标共享,引起的错误路径。下面我们重新收集一下统计量,采用no_invaliate为true的情况。



SQL> exec dbms_stats.flush_database_monitoring_info;


PL/SQL procedure successfully completed




SQL> exec dbms_stats.gather_table_stats(user,'T',cascade => true,no_invalidate => true,method_opt => 'for columns size 10 object_id');

PL/SQL procedure successfully completed



新统计量生成,我们使用explain plan查看一下,此时SQL应该采用的执行计划是什么?




SQL> explain plan for select /*+demo*/object_id, owner from t where object_id=1000;

Explained



SQL> select * from table(dbms_xplan.display);



PLAN_TABLE_OUTPUT


--------------------------------------------------------


Plan hash value: 1601196873


---------------------------------------------------------


| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |


--------------------------------------------------------------------------


| 0 | SELECT STATEMENT | | 72722 | 639K| 266 (1)| 00:00:04 |


|* 1 | TABLE ACCESS FULL| T | 72722 | 639K| 266 (1)| 00:00:04 |


--------------------------------------------------------------------------


Predicate Information (identified by operation id):


---------------------------------------------------


1 - filter("OBJECT_ID"=1000)


13 rows selected



此时,FTS全表扫描是更好的选择。但是我们查看一下实际执行时候,路径情况。




SQL> select /*+demo*/object_id, owner from t where object_id=1000;


已选择72729行。



统计信息


----------------------------------------------------------


0 recursive calls


0 db block gets


10907 consistent gets


0 physical reads


0 redo size


72729 rows processed



SQL> select sql_id, executions, version_count from v$sqlarea where sql_text like 'select /*+demo*/%';


SQL_ID