全域性臨時表GTT的統計資訊收集辦法:

531968912發表於2017-07-10

我們都知道,全域性臨時表GTT分為兩種,一種是transaction level,一種是session level,

分別透過on commit delete rows/preserve rows實現,其中session level表示在本sessoin
資料有效,相同session內,之前事務操作的資料,對於後續的操作都可見,而事務級的GTT表示
一旦事務結束(commit)那麼立即delete,相同session 的後續操作看不到之前事務操作。
在9i階段可以使用GATHER_TABLE_STATS呼叫來收集統計資訊須傳入引數GATHER_TEMP為TRUE,
10g開始oracle對於普通表和GTT收集統計資訊並沒有特殊處理,都是透過GATHER_TABLE_STATS
儲存過程來收集,但是由於上述的兩種GTT特殊性,收集統計資訊有特殊性:

1.對於session level的,因為GTT資料並不持久化,存在session 隔離性,需要在當前session 收集,
若是透過另起視窗(新session)收集統計資訊會不成功,原因就是收集統計資訊的session 沒有資料,
自然也收集不到統計資訊了。

2.對於transaction level的,即便是當前session 收集,因為GATHER_TABLE_STATS會先執行預設提交,
所以資料就自動刪除,自然也就沒有資料可收集了。所以針對這種情景,oracle 有官方note 403587.1介紹
下面就是移花接木辦法來收集事務級GTT的步驟
1. create a PRESERVE ROWS table
SQL> create global temporary table TT(I number) on commit preserve rows;
2. populate with representative data
SQL> insert into TT select rownum from dba_objects where rownum<1000;
3. gather stats
SQL> exec dbms_stats.gather_table_stats(null,'TT');
4. create a STAT table
SQL> exec dbms_stats.create_stat_table(null,'TTSTATS');
5. export the stats from the PRESERVE ROWS table
SQL> exec dbms_stats.export_table_stats(null,'TT',null,'TTSTATS',null,true);
6. truncate then drop the PRESERVE ROWS table
SQL> truncate table TT;
SQL> drop table TT;
7. now create the real temporary table (defined using DELETE ROWS - the default)
SQL> create global temporary table TT(I number);
8. finally import the stats exported from the STAT table
SQL> exec dbms_stats.import_table_stats(null,'TT',null,'TTSTATS',null,true);

3.在12c版本,oracle已經進步改善了對這種transaction level GTT的統計資訊收集,
也就是說GATHER_TABLE_STATS收集統計資訊的時候不會預設發起commit,這樣就不會
破壞當前session的事務完整性,收集統計資訊的儲存過程就可以看到當前session的
資料情況並收集統計資訊。
下面是一個簡單的測試過程:
3.1.建立transaction level GTT
Create Global Temporary Table maob_temp  (a number,b varchar2(100)) On Commit delete Rows; <<delete Rows
Table created.

3.2.插入資料
insert into maob_temp select rownum,object_name from dba_objects where rownum<1000;
SQL>

999 rows created.

3.3.收集統計資訊
exec dbms_stats.gather_table_stats(user,'MAOB_TEMP');
SQL>
PL/SQL procedure successfully completed.

3.4.check是否資料已經被刪除
 select count(*)from maob_temp;
SQL>
  COUNT(*)
----------
       999

3.5.檢視統計資訊是否已經收整合功 
SQL> select TABLE_NAME,NUM_ROWS,BLOCKS,SCOPE from DBA_TAB_STATISTICS where owner='MAOB' AND TABLE_NAME='MAOB_TEMP';

TABLE_NAME    NUM_ROWS BLOCKS SCOPE
--------------------------------------
MAOB_TEMP    0      0 SHARED
MAOB_TEMP  999      4 SESSION <<<<

注意:這一步要在和上述步驟相同的session執行,因為12c的這個新功能預設對GTT收集統計資訊是session scope的,也就是說統計資訊也是
session 隔離的,其他session 看不到這個session收集的統計資訊,若是變成傳統的shared scope,那麼仍然會預設先commit再收集
統計資訊並記錄資料字典表,供其他session 使用,對於transaction level仍然存在先commit在收集情況,那麼要解決問題,仍需要參考步驟
2的移花接木辦法,但是建立表之後要先指定為shared scope再收集統計資訊。
EXEC DBMS_STATS.SET_TABLE_PREFS (NULL,'TT','GLOBAL_TEMP_TABLE_STATS','SHARED');

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/25462274/viewspace-2141844/,如需轉載,請註明出處,否則將追究法律責任。

相關文章