建立索引不會級聯收集表的統計資訊?
開發DBA,對Oracle大表治理流程如下:
1.建立temp表,與生產環境大表相同表結構;
2.對生產環境大表rename to table_name_bak;
3.對temp表 rename to table_name 生產環境表;
4.此時新的業務表無資料,insert into table_name select * from table_name_bak where date>sysdate-31;
5.對新建的表,同步bak表的索引!
6.SQL測試,發現存在效能問題,非常慢,原本執行SQL很快,大表幾十G,新的表才30W條記錄???
統計資訊的問題,收集後OK
exec dbms_stats.gather_table_stats(ownname=>'A',tabname=>'B',cascade=>true,degree=>6,estimate_percent=>50);
?為啥?
實驗測試:
SQL> create table a as select * from dba_objects; SQL> create index a_id on a(object_id); SQL> set autotrace on SQL> select count(*) from a where object_id=7788 order by object_id; COUNT(*) ---------- 1Execution Plan ---------------------------------------------------------- Plan hash value: 2227953900 ------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0| SELECT STATEMENT | | 1 | 13 | 1 (0)| 00:00:01 | | 1 | SORT AGGREGATE | | 1 | 13 | | | |* 2 | INDEX RANGE SCAN| A_ID | 1 | 13 | 1 (0)| 00:00:01 | -------------------------------------------------------------------------- Predicate Information (identified by operation id): --------------------------------------------------- 2 - access("OBJECT_ID"=7788) Note ----- - dynamic sampling used for this statement (level=2)
本次測試的舉例不太好,因為SQL走了索引,但是為啥SQL走了索引呢? 是由於ORACLE 11G動態取樣,ORACLE執行計劃選擇對了。
但是生產環境,動態取樣後,Oracle發現走索引成本更高,走全表掃描了!!!
SQL> SELECT NUM_ROWS,EMPTY_BLOCKS,BLOCKS,LAST_ANALYZED FROM DBA_TABLES WHERE OWNER='YZ' AND TABLE_NAME='A';
NUM_ROWS EMPTY_BLOCKS BLOCKS LAST_ANAL
---------- ------------ ---------- ---------
SQL> SELECT NUM_ROWS,SAMPLE_SIZE,LEAF_BLOCKS,LAST_ANALYZED FROM DBA_INDEXES WHERE TABLE_OWNER='YZ' AND TABLE_NAME='A';
NUM_ROWS SAMPLE_SIZE LEAF_BLOCKS LAST_ANAL
---------- ----------- ----------- ---------
87096 87096 193 28-APR-20
表統計資訊0,因此生產環境的問題,就是建立索引,這個只會收集索引統計資訊,而非級聯表,SQL執行動態採用,資料不準確,導致最終的SQL執行計劃選擇全表掃描,SQL執行緩慢。 收集統計資訊後,表資料量準確,重新生成都執行計劃,選擇了正確的執行計劃!!!