Oracle全域性臨時表

lhrbest發表於2017-06-19

Oracle全域性臨時表




目前所有使用Oracle作為資料庫支撐平臺的應用,大部分是資料量比較龐大的系統,即表的資料量級一般情況下都是在百萬級以上。當然,在Oracle中建立分割槽是一種不錯的選擇,但是當發現應用有多張表關聯的時候,並且這些表大部分都比較龐大,而關聯的時候發現其中的某一張或者某幾張表關聯之後得到的結果集非常小,並且查詢得到這個結果集的速度非常快,那麼這個時候考慮在Oracle中建立“臨時表”。

在建立資料表的時候,如果沒有特殊地指明,那麼建立的表是一個永久的關係型表,也就是說,這個表中對應的資料,除非是顯式地刪除,否則表中的資料是永遠都存在的。相對應的,在Oracle資料庫中,還有一種型別的表,叫做臨時表。這個臨時表跟永久表最大的區別就是表中的資料不會永遠地存在。當一個會話結束或者事務結束的時候,這個臨時表中的資料,不用使用者自己刪除,資料庫自己會自動清除。

Oracle的臨時表建立之後基本不佔用表空間,如果沒有指定臨時表(包括臨時表的索引)存放的表空間,那麼插入到臨時表的資料是存放在Oracle系統的預設臨時表空間中(TEMP),一個系統可能有多個臨時表空間。臨時表的資料只能存放在臨時表空間中。

臨時表的資料只是在事務期間存在,對於會話型別的臨時表,資料在會話期間存在會話的資料對於當前會話私有每個會話只能看到並修改自己的資料。DML鎖不會加到臨時表的資料上。可以對臨時表建立索引檢視、觸發器,可以用expimp工具匯入匯出表的定義,但是不能匯出資料。

(一)臨時表的特點

多使用者操作的獨立性:對於使用同一張臨時表的不同使用者,Oracle都會分配一個獨立的TEMP SEGMENT,這樣就避免了多個使用者在對同一張臨時表操作時發生交叉,從而保證了多個使用者操作的併發性和獨立性。

資料的臨時性:既然是臨時表,顧名思義,存放在該表中的資料是臨時性的。Oracle根據建立臨時表時指定的引數(ON COMMIT DELETE ROWS /ON COMMIT PRESERVE ROWS),自動將資料TRUNCATE掉。

(二)臨時表的分類

Oracle資料庫根據臨時表的性質不同,可以分為事務臨時表(ON COMMIT DELETE ROWS)與會話臨時表(ON COMMIT PRESERVE ROWS)。

1、事務臨時表

事務臨時表是指資料只有在當前事務內有效,該臨時表與事務相關,當進行事務提交或者事務回滾的時候,臨時表中的資料將自動被清空,其它的內容和會話級的臨時表的一致(包括退出SESSION的時候,事務級的臨時表的資料也會被清空)。一般情況下,如果在建立資料表的時候,沒有特殊指明表是會話臨時表的話,那麼該表預設為事務臨時表。

以下三種情況下,事務臨時表中的資料就會被清空:

① 提交事務(COMMIT

② 回滾事務(ROLLBACK

③ 退出SESSION

建立事務臨時表的語法如下所示

CREATE GLOBAL TEMPORARY TABLE  TABLE_NAME

(COL1 TYPE1,COL2 TYPE2...)

[ON COMMIT DELETE ROWS];

事務臨時表示例如下所示:

SYS@lhrdb> CREATE GLOBAL TEMPORARY TABLE CGTT_DELETE_LHR AS SELECT * FROM SCOTT.EMP WHERE 1=2;

Table created.

SYS@lhrdb> INSERT INTO CGTT_DELETE_LHR SELECT * FROM SCOTT.EMP WHERE ROWNUM<=5;

5 rows created.

SYS@lhrdb> SELECT * FROM CGTT_DELETE_LHR;

     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO

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

      7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800                    20

      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30

      7521 WARD       SALESMAN        7698 1981-02-22 00:00:00       1250        500         30

      7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975                    20

      7654 MARTIN     SALESMAN        7698 1981-09-28 00:00:00       1250       1400         30

SYS@lhrdb> COMMIT;

Commit complete.

SYS@lhrdb>  SELECT * FROM CGTT_DELETE_LHR;

no rows selected

從示例中可以看到,當執行完COMMIT後,當前會話就看不到資料了。

2、會話臨時表

會話臨時表,顧名思義,是指資料只在當前會話內是有效的臨時表。關閉當前會話或者進行新的連線之後,資料表中的內容就會被清除。

CREATE GLOBAL TEMPORARY TABLE  TABLE_NAME

(COL1 TYPE1,COL2 TYPE2...)

ON COMMIT PRESERVE ROWS;

會話臨時表示例如下所示:

SYS@lhrdb> CREATE GLOBAL TEMPORARY TABLE CGTT_PRESERVE_LHR ON COMMIT PRESERVE ROWS AS SELECT * FROM SCOTT.EMP WHERE 1=2;

Table created.

SYS@lhrdb> INSERT INTO CGTT_PRESERVE_LHR SELECT * FROM SCOTT.EMP WHERE ROWNUM<=5;

5 rows created.

SYS@lhrdb> SELECT * FROM CGTT_PRESERVE_LHR;

     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO

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

      7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800                    20

      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30

      7521 WARD       SALESMAN        7698 1981-02-22 00:00:00       1250        500         30

      7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975                    20

      7654 MARTIN     SALESMAN        7698 1981-09-28 00:00:00       1250       1400         30

SYS@lhrdb> COMMIT;

Commit complete.

SYS@lhrdb> SELECT * FROM CGTT_PRESERVE_LHR;

     EMPNO ENAME      JOB              MGR HIREDATE                   SAL       COMM     DEPTNO

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

      7369 SMITH      CLERK           7902 1980-12-17 00:00:00        800                    20

      7499 ALLEN      SALESMAN        7698 1981-02-20 00:00:00       1600        300         30

      7521 WARD       SALESMAN        7698 1981-02-22 00:00:00       1250        500         30

      7566 JONES      MANAGER         7839 1981-04-02 00:00:00       2975                    20

      7654 MARTIN     SALESMAN        7698 1981-09-28 00:00:00       1250       1400         30

SYS@lhrdb> CONN / AS SYSDBA

Connected.

SYS@lhrdb> SELECT * FROM CGTT_PRESERVE_LHR;

no rows selected

從示例中可以看到,當執行完COMMIT後,資料依然存在,但是當重新連線會話後,資料就被清空了。

檢視一張表是否臨時表,可以從DBA_TABLES檢視的DURATION列來查詢:

SELECT UT.TABLE_NAME,

       UT.TABLESPACE_NAME,

       UT.TEMPORARY,

       DECODE(UT.DURATION,'SYS$SESSION','會話級','SYS$TRANSACTION','事務級') 臨時表型別

  FROM DBA_TABLES UT

 WHERE UT.TEMPORARY = 'Y'

   AND UT.TABLE_NAME LIKE '%CGTT%';


TABLE_NAME                     TABLESPACE_NAME                T TYPE

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

CGTT_DELETE_LHR                                               Y 事務級

CGTT_PRESERVE_LHR                                             Y 會話級


會話臨時表與事務臨時表主要的差異就在於刪除資料的時機不同。事務臨時表是在事務提交或回滾的時候清除資料,而會話臨時表則是在關閉當前會話的時候清除資料。只要當前會話沒有關閉,即使事務完成了,會話臨時表中的資料仍然存在,不會被清除。

(三)臨時表的統計資訊

臨時表預設是不收集統計資訊的,但是可以使用DBMS_STATS.GATHER_SCHEMA_STATSSCHEMA級別收集,需要設定GATHER_TEMPTRUE(預設為FALSE);也可以和普通表一樣使用GATHER_TABLE_STATS在表級別來收集。需要注意的是,只能收集會話臨時表的統計資訊,不能收集事務臨時表的統計資訊。會話臨時表的統計資訊是被所有的會話所共享的,所以,在一般情況下,不建議收集臨時表的統計資訊,否則可能會導致很嚴重的資料庫效能問題。臨時表的統計資訊在生成執行計劃時一般是被動態取樣的。

下面給出一個示例,該示例演示了由於收集了臨時表的統計資訊引發的效能問題。

環境準備:

DROP TABLE T_20170619_LHR CASCADE CONSTRAINTS PURGE;

DROP TABLE T_CGTT_20170619_LHR CASCADE CONSTRAINTS PURGE;


CREATE TABLE T_20170619_LHR (

  ID NUMBER NOT NULL,

  N NUMBER,

  CONTENTS VARCHAR2(4000)

);


CREATE GLOBAL TEMPORARY TABLE T_CGTT_20170619_LHR (

 ID NUMBER NOT NULL,

 T_ID NUMBER NOT NULL,

 N NUMBER,

 CONTENTS VARCHAR2(4000)

) ON COMMIT PRESERVE ROWS

;


EXECUTE DBMS_RANDOM.SEED(0);

INSERT INTO T_20170619_LHR

SELECT  ROWNUM,  ROWNUM, DBMS_RANDOM.STRING('A', 50)

FROM DUAL

CONNECT BY LEVEL <= 10

ORDER BY DBMS_RANDOM.RANDOM;


INSERT INTO T_CGTT_20170619_LHR

SELECT ROWNUM, ROWNUM, ROWNUM, DBMS_RANDOM.STRING('B', 50)

FROM DUAL CONNECT BY LEVEL <= 100000

ORDER BY DBMS_RANDOM.RANDOM;

COMMIT;


SELECT COUNT(*) FROM T_20170619_LHR; --10

SELECT COUNT(*) FROM T_CGTT_20170619_LHR; --100000

EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'LHR',TABNAME => 'T_20170619_LHR',ESTIMATE_PERCENT => 100,CASCADE=>TRUE);

正常的執行計劃如下:

SET LINESIZE 1000

ALTER SESSION SET STATISTICS_LEVEL=ALL ;

SELECT *

FROM T_20170619_LHR A,T_CGTT_20170619_LHR B

WHERE A.ID = B.T_ID;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST ADVANCED'));


PLAN_TABLE_OUTPUT

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

SQL_ID  awa3ys5000qc1, child number 0

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

SELECT * FROM T_20170619_LHR A,T_CGTT_20170619_LHR B WHERE A.ID = B.T_ID


Plan hash value: 1110746760


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

| Id  | Operation          | Name                | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |

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

|   0 | SELECT STATEMENT   |                     |      1 |        |       |   272 (100)|          |     10 |00:00:00.03 |     990 |       |       |          |

|*  1 |  HASH JOIN         |                     |      1 |     10 | 20980 |   272   (1)| 00:00:04 |     10 |00:00:00.03 |     990 |   821K|   821K| 1142K (0)|

|   2 |   TABLE ACCESS FULL| T_20170619_LHR      |      1 |     10 |   570 |     3   (0)| 00:00:01 |     10 |00:00:00.01 |       6 |       |       |          |

|   3 |   TABLE ACCESS FULL| T_CGTT_20170619_LHR |      1 |  90611 |   176M|   268   (1)| 00:00:04 |    100K|00:00:00.01 |     984 |       |       |          |

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

Query Block Name / Object Alias (identified by operation id):

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


   1 - SEL$1

   2 - SEL$1 / A@SEL$1

   3 - SEL$1 / B@SEL$1


Outline Data

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


  /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')

      DB_VERSION('11.2.0.3')

      ALL_ROWS

      OUTLINE_LEAF(@"SEL$1")

      FULL(@"SEL$1" "A"@"SEL$1")

      FULL(@"SEL$1" "B"@"SEL$1")

      LEADING(@"SEL$1" "A"@"SEL$1" "B"@"SEL$1")

      USE_HASH(@"SEL$1" "B"@"SEL$1")

      END_OUTLINE_DATA

  */


Predicate Information (identified by operation id):

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


   1 - access("A"."ID"="B"."T_ID")


Column Projection Information (identified by operation id):

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


   1 - (#keys=1) "A"."ID"[NUMBER,22], "B"."T_ID"[NUMBER,22], "A"."CONTENTS"[VARCHAR2,4000], "A"."N"[NUMBER,22], "B"."ID"[NUMBER,22],

       "B"."CONTENTS"[VARCHAR2,4000], "B"."N"[NUMBER,22]

   2 - "A"."ID"[NUMBER,22], "A"."N"[NUMBER,22], "A"."CONTENTS"[VARCHAR2,4000]

   3 - "B"."ID"[NUMBER,22], "B"."T_ID"[NUMBER,22], "B"."N"[NUMBER,22], "B"."CONTENTS"[VARCHAR2,4000]


Note

-----

   - dynamic sampling used for this statement (level=2)

這個時候執行計劃是正確的,因為T_20170619_LHR是小表(共10行資料),而T_CGTT_20170619_LHR是大表(共100000行資料),處於被驅動的位置,是正確的,而且在執行中,Oracle對大表使用了動態取樣。下面新開一個會話,然後收集全域性臨時表T_CGTT_20170619_LHR表的統計資訊,如下:

SYS@orclasm > SELECT TABLE_NAME,

  2         PARTITION_NAME,

  3         LAST_ANALYZED,

  4         PARTITION_POSITION,

  5         NUM_ROWS

  6    FROM DBA_TAB_STATISTICS T

  7   WHERE TABLE_NAME = 'T_CGTT_20170619_LHR';


TABLE_NAME                     PARTITION_NAME                 LAST_ANALYZED       PARTITION_POSITION   NUM_ROWS

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

T_CGTT_20170619_LHR


SYS@orclasm > EXEC DBMS_STATS.GATHER_TABLE_STATS(OWNNAME => 'LHR',TABNAME => 'T_CGTT_20170619_LHR',ESTIMATE_PERCENT => 100,CASCADE=>TRUE,NO_INVALIDATE => FALSE);  --注意這裡要加NO_INVALIDATE => FALSE


PL/SQL procedure successfully completed.


SYS@orclasm > SELECT TABLE_NAME,

  2         PARTITION_NAME,

  3         LAST_ANALYZED,

  4         PARTITION_POSITION,

  5         NUM_ROWS

  6    FROM DBA_TAB_STATISTICS T

  7   WHERE TABLE_NAME = 'T_CGTT_20170619_LHR';


TABLE_NAME                     PARTITION_NAME                 LAST_ANALYZED       PARTITION_POSITION   NUM_ROWS

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

T_CGTT_20170619_LHR                                           2017-06-19 15:30:24                             0

然後回到剛才的會話,繼續查詢執行計劃,發現執行計劃變動了:

SET LINESIZE 1000

ALTER SESSION SET STATISTICS_LEVEL=ALL ;

SELECT *

FROM T_20170619_LHR A,T_CGTT_20170619_LHR B

WHERE A.ID = B.T_ID;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST ADVANCED'));


PLAN_TABLE_OUTPUT

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

SQL_ID  awa3ys5000qc1, child number 0

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

SELECT * FROM T_20170619_LHR A,T_CGTT_20170619_LHR B WHERE A.ID = B.T_ID


Plan hash value: 991471220


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

| Id  | Operation          | Name                | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |

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

|   0 | SELECT STATEMENT   |                     |      1 |        |       |     6 (100)|          |     10 |00:00:00.05 |     989 |       |       |          |

|*  1 |  HASH JOIN         |                     |      1 |      1 |  2098 |     6  (17)| 00:00:01 |     10 |00:00:00.05 |     989 |    10M|  2143K|   11M (0)|

|   2 |   TABLE ACCESS FULL| T_CGTT_20170619_LHR |      1 |      1 |  2041 |     2   (0)| 00:00:01 |    100K|00:00:00.01 |     982 |       |       |          |

|   3 |   TABLE ACCESS FULL| T_20170619_LHR      |      1 |     10 |   570 |     3   (0)| 00:00:01 |     10 |00:00:00.01 |       7 |       |       |          |

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

Query Block Name / Object Alias (identified by operation id):

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


   1 - SEL$1

   2 - SEL$1 / B@SEL$1

   3 - SEL$1 / A@SEL$1


Outline Data

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


  /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')

      DB_VERSION('11.2.0.3')

      ALL_ROWS

      OUTLINE_LEAF(@"SEL$1")

      FULL(@"SEL$1" "B"@"SEL$1")

      FULL(@"SEL$1" "A"@"SEL$1")

      LEADING(@"SEL$1" "B"@"SEL$1" "A"@"SEL$1")

      USE_HASH(@"SEL$1" "A"@"SEL$1")

      END_OUTLINE_DATA

  */


Predicate Information (identified by operation id):

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


   1 - access("A"."ID"="B"."T_ID")


Column Projection Information (identified by operation id):

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


   1 - (#keys=1) "B"."T_ID"[NUMBER,22], "A"."ID"[NUMBER,22], "B"."ID"[NUMBER,22], "B"."CONTENTS"[VARCHAR2,4000], "B"."N"[NUMBER,22],

       "A"."CONTENTS"[VARCHAR2,4000], "A"."N"[NUMBER,22]

   2 - "B"."ID"[NUMBER,22], "B"."T_ID"[NUMBER,22], "B"."N"[NUMBER,22], "B"."CONTENTS"[VARCHAR2,4000]

   3 - "A"."ID"[NUMBER,22], "A"."N"[NUMBER,22], "A"."CONTENTS"[VARCHAR2,4000]

可見,沒有使用動態取樣,而且生成的執行計劃是錯誤的,因為大表(10W條記錄)竟然做了驅動表。當刪除臨時表的統計資訊後,執行計劃恢復正常:

LHR@orclasm > EXEC DBMS_STATS.DELETE_TABLE_STATS(OWNNAME => 'LHR',TABNAME => 'T_CGTT_20170619_LHR',NO_INVALIDATE => FALSE);


PL/SQL procedure successfully completed.


SET LINESIZE 1000

ALTER SESSION SET STATISTICS_LEVEL=ALL ;

SELECT *

FROM T_20170619_LHR A,T_CGTT_20170619_LHR B

WHERE A.ID = B.T_ID;

SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL,NULL,'ALLSTATS LAST ADVANCED'));


PLAN_TABLE_OUTPUT

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

SQL_ID  awa3ys5000qc1, child number 0

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

SELECT * FROM T_20170619_LHR A,T_CGTT_20170619_LHR B WHERE A.ID = B.T_ID


Plan hash value: 1110746760


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

| Id  | Operation          | Name                | Starts | E-Rows |E-Bytes| Cost (%CPU)| E-Time   | A-Rows |   A-Time   | Buffers |  OMem |  1Mem | Used-Mem |

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

|   0 | SELECT STATEMENT   |                     |      1 |        |       |   272 (100)|          |     10 |00:00:00.03 |     990 |       |       |          |

|*  1 |  HASH JOIN         |                     |      1 |     10 | 20980 |   272   (1)| 00:00:04 |     10 |00:00:00.03 |     990 |   821K|   821K| 1142K (0)|

|   2 |   TABLE ACCESS FULL| T_20170619_LHR      |      1 |     10 |   570 |     3   (0)| 00:00:01 |     10 |00:00:00.01 |       6 |       |       |          |

|   3 |   TABLE ACCESS FULL| T_CGTT_20170619_LHR |      1 |  90611 |   176M|   268   (1)| 00:00:04 |    100K|00:00:00.01 |     984 |       |       |          |

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

Query Block Name / Object Alias (identified by operation id):

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


   1 - SEL$1

   2 - SEL$1 / A@SEL$1

   3 - SEL$1 / B@SEL$1


Outline Data

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


  /*+

      BEGIN_OUTLINE_DATA

      IGNORE_OPTIM_EMBEDDED_HINTS

      OPTIMIZER_FEATURES_ENABLE('11.2.0.3')

      DB_VERSION('11.2.0.3')

      ALL_ROWS

      OUTLINE_LEAF(@"SEL$1")

      FULL(@"SEL$1" "A"@"SEL$1")

      FULL(@"SEL$1" "B"@"SEL$1")

      LEADING(@"SEL$1" "A"@"SEL$1" "B"@"SEL$1")

      USE_HASH(@"SEL$1" "B"@"SEL$1")

      END_OUTLINE_DATA

  */


Predicate Information (identified by operation id):

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


   1 - access("A"."ID"="B"."T_ID")


Column Projection Information (identified by operation id):

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


   1 - (#keys=1) "A"."ID"[NUMBER,22], "B"."T_ID"[NUMBER,22], "A"."CONTENTS"[VARCHAR2,4000], "A"."N"[NUMBER,22], "B"."ID"[NUMBER,22],

       "B"."CONTENTS"[VARCHAR2,4000], "B"."N"[NUMBER,22]

   2 - "A"."ID"[NUMBER,22], "A"."N"[NUMBER,22], "A"."CONTENTS"[VARCHAR2,4000]

   3 - "B"."ID"[NUMBER,22], "B"."T_ID"[NUMBER,22], "B"."N"[NUMBER,22], "B"."CONTENTS"[VARCHAR2,4000]


Note

-----

   - dynamic sampling used for this statement (level=2)


所以,對於臨時表儘量使用動態取樣,而不應該收集它的統計資訊。因為統計資訊被所有會話所共享,而全域性臨時表的資料是與會話相關的,不同的會話其含有的資料量是不同的。


真題1、 You issued the following command:

CREATE GLOBAL TEMPORARY TABLE admin_work_area

(startdate DATE,

enddate DATE,

class CHAR(20))

ON COMMIT DELETE ROWS

TABLESPACE tbs_t1;

An index is then created on the ADMIN_WORK_AREA temporary table.  Which two statements are true regarding the TBS_T1 tablespace in the above command? (Choose two.)

AIt stores only the temporary table but not its indexes.

BIt stores both the temporary table as well as its indexes.

CIt must be a nondefault temporary tablespace for the database.

DIt can be a default or nondefault temporary tablespace for the database.

EIt must be the default temporary tablespace of the user who issues the command.

答案:BD

本題中的命令是在TBS_T1表空間中建立了一個事務臨時表ADMIN_WORK_AREA,並且在該臨時表上建立了一個索引,最後要求選出有關TBS_T1表空間的2個正確的選項。

本題中,對於選項ATBS_T1表空間只存資料而不存索引,說法錯誤,應該都儲存。所以,選項A錯誤。

對於選項BTBS_T1表空間即儲存資料也儲存索引,說法正確。所以,選項B正確。

對於選項CTBS_T1表空間必須是非預設的表空間,說法錯誤,預設和非預設都可以。所以,選項C錯誤。

對於選項DTBS_T1表空間可以是一個預設或非預設的資料庫的臨時表空間。所以,選項D正確。

對於選項ETBS_T1表空間必須是預設的表空間,說法錯誤,預設和非預設都可以。所以,選項E錯誤。

所以,本題的答案為BD









    臨時表(Tempotary table)用於儲存事務或會話期間的中間結果集。臨時表中儲存的資料只對當前會話可見,所有會話都看不到其他會話的資料;即使當前會話已經提交了(commit)資料,別的會話也看不到它的資料。對於臨時表,不存在多使用者併發的問題,因為一個會話不會因為使用一個臨時表而阻塞另一個會話。即使我們“鎖住”了臨時表,也不會妨礙其他會話使用臨時表。

     

    臨時表比常規表生成的redo少得多。不過由於臨時表必須為其中包含的資料生成undo資訊,所以也會生成一定的redo。update和delete會生成最多的undo,insert和select生成的undo最少。

 

    臨時表會從當前登入使用者的臨時表空間分配儲存空間,或者如果從一個定義者許可權過程訪問臨時表,就會使用該過程所有者的臨時表空間。全域性臨時表實際上是表本身的一個模板。建立臨時表的動作不涉及儲存空間分配,不會為此初始區段,這與常規表有所不同。對於臨時表,執行時當一個會話第一次在臨時表中放入資料時,才會為該會話建立一個臨時段。由於每個回話會得到其自己的臨時段(而不是一個現有段的一個區段),每個使用者可能在不同的表空間為其看in是表分配空間。USER1的臨時表空間可能設定為TEMP1,因此他的臨時表會從這個表空間分配。USER2可能把TEMP2作為其臨時表空間,它的臨時表就會從那裡分配。

 

   Oracle的臨時表與其他關聯式資料庫中的臨時表類似,主要區別是:Oracle的臨時表是“靜態”定義的。每個資料庫只建立一次臨時表,而不是為資料庫中的每個儲存過程都建立一次。在Oracle歷史表一定存在,他們作為物件放在資料字典中,但是在會話向臨時表中放入資料之前,臨時表看上去總是空的。由於臨時表是靜態定義的,所以你能建立引用臨時表的檢視,還可以建立儲存過程只用靜態SQL來引用臨時表,等等。

 

    臨時表可以是會話的(臨時表中的資料可以跨提交存在,即提交之前仍然存在,但是斷開連線後再連線時資料就沒有了),也可以是基於事務的(提交之後資料就消失)。語法如下:

  • 基於會話  create global temporary table temp_table_session (...)  on commit preserve rows

         基於會話的臨時表,在會話斷開之前,或者通過一個delete或truncate物理地刪除行之前,這些行會一直存在於這個臨時表中。只有我的會話能看到這些行,即使我已經提交,其他會話也無法看到我的行。

  • 基於事務   create global temporary table temp_table_session (...)  on commit delete rows

          基於事務的臨時表,我的會話提交時,臨時表中的行就不見了。只需把分配給這個表的臨時區段交回,這些行就會消失,在臨時表的自動清除過程中不存在開銷。

 

   

       臨時表可以有永久表的許多屬性。他們可以有觸發器,檢查約束,索引等。但永久表的某些特性在臨時表中並不支援,這包括以下特性。

  • 不能有引用完整性約束。臨時表不能作為外來鍵的目標,也不能在臨時表中定義外來鍵。
  • 不能是IOT
  • 不能在任何型別的聚簇中
  • 不能分割槽
  • 不能通過ANALYZE表命令生成統計資訊

        在所有資料庫中,臨時表的缺點之一就是優化器不能正常地得到臨時表的真實統計資訊。使用基於代價的優化器(CBO)時,有效的統計對於優化器的成敗至關重要。


全域性臨時表的統計資訊是不能被收集的,如果被收集,它的統計資訊肯定為0,會造成執行計劃不準,所以要鎖定它的統計資訊,禁止系統自動收集。



Oracle臨時表使用注意事項 

 此文將給出在使用Oracle臨時表的過程中需要注意的事項,並對這些特點進行驗證。
  臨時表不支援物化檢視
  可以在臨時表上建立索引
  
可以基於臨時表建立檢視
  
臨時表結構可被匯出,但內容不可以被匯出
  
臨時表通常是建立在使用者的臨時表空間中的,不同使用者可以有自己的獨立的臨時表空間
  
不同的session不可以互相訪問對方的臨時表資料
  臨時表資料將不會上DML(Data Manipulation Language)鎖


1.
臨時表不支援物化檢視
1)環境準備
(1)建立基於會話的臨時表
sec@ora10g> create global temporary table t_temp_session (x int) on commit preserve rows;

Table created.

sec@ora10g> col TABLE_NAME for a30
sec@ora10g> col TEMPORARY for a10
sec@ora10g> select TABLE_NAME,TEMPORARY from user_tables where table_name = 'T_TEMP_SESSION';

TABLE_NAME                     TEMPORARY
------------------------------ ----------
T_TEMP_SESSION                 Y

(2)初始化兩條資料
sec@ora10g> insert into t_temp_session values (1);

1 row created.

sec@ora10g> insert into t_temp_session values (2);

1 row created.

sec@ora10g> commit;

Commit complete.

sec@ora10g> select * from t_temp_session;

         X
----------
         1
         2

(3)在臨時表
T_TEMP_SESSION上新增主鍵
sec@ora10g> alter table T_TEMP_SESSION add constraint PK_T_TEMP_SESSION primary key(x);

Table altered.

2)在臨時表T_TEMP_SESSION上建立物化檢視
(1)建立物化檢視日誌日誌
sec@ora10g> create materialized view log on T_TEMP_SESSION with sequence, rowid (x) including new values;
create materialized view log on T_TEMP_SESSION with sequence, rowid (x) including new values
*
ERROR at line 1:
ORA-14451: unsupported feature with temporary table

可見,在建立物化檢視時便提示,臨時表上無法建立物化檢視日誌。

(2)建立物化檢視
sec@ora10g> create materialized view mv_T_TEMP_SESSION build immediate refresh fast on commit enable query rewrite as select * from T_TEMP_SESSION;
create materialized view mv_T_TEMP_SESSION build immediate refresh fast on commit enable query rewrite as select * from T_TEMP_SESSION
                                                                                                                        *
ERROR at line 1:
ORA-23413: table "SEC"."T_TEMP_SESSION" does not have a materialized view log

由於物化檢視日誌沒有建立成功,因此顯然物化檢視亦無法建立。

2.在臨時表上建立索引
sec@ora10g> create index i_t_temp_session on t_temp_session (x);

Index created.

臨時表上索引建立成功。

3.基於臨時表建立檢視
sec@ora10g> create view v_t_temp_session as select * from t_temp_session where x<100;

View created.

基於臨時表的檢視建立成功。

4.臨時表結構可被匯出,但內容不可以被匯出
1)使用exp工具備份臨時表
ora10g@secdb /home/oracle$ exp sec/sec file=t_temp_session.dmp log=t_temp_session.log tables=t_temp_session

Export: Release 10.2.0.1.0 - Production on Wed Jun 29 22:06:43 2011

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
Export done in WE8ISO8859P1 character set and AL16UTF16 NCHAR character set

About to export specified tables via Conventional Path ...
. . exporting table                 T_TEMP_SESSION
Export terminated successfully without warnings.


可見在備份過程中,沒有顯示有資料被匯出。

2)使用imp工具的show選項檢視備份介質中的SQL內容
ora10g@secdb /home/oracle$ imp sec/sec file=t_temp_session.dmp full=y show=y

Import: Release 10.2.0.1.0 - Production on Wed Jun 29 22:06:57 2011

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

Export file created by EXPORT:V10.02.01 via conventional path
import done in WE8ISO8859P1 character set and AL16UTF16 NCHAR character set
. importing SEC's objects into SEC
. importing SEC's objects into SEC
 "CREATE GLOBAL TEMPORARY TABLE "T_TEMP_SESSION" ("X" NUMBER(*,0)) ON COMMIT "
 "PRESERVE ROWS "
 "CREATE INDEX "I_T_TEMP_SESSION" ON "T_TEMP_SESSION" ("X" ) "
Import terminated successfully without warnings.


這裡體現了建立臨時表和索引的語句,因此臨時表的結構資料是可以被匯出的。

3)嘗試匯入資料
ora10g@secdb /home/oracle$ imp sec/sec file=t_temp_session.dmp full=y ignore=y

Import: Release 10.2.0.1.0 - Production on Wed Jun 29 22:07:16 2011

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to: Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

Export file created by EXPORT:V10.02.01 via conventional path
import done in WE8ISO8859P1 character set and AL16UTF16 NCHAR character set
. importing SEC's objects into SEC
. importing SEC's objects into SEC
Import terminated successfully without warnings.

依然顯示沒有記錄被匯入。

5.檢視臨時表空間的使用情況
可以通過查詢V$SORT_USAGE檢視獲得相關資訊。
sec@ora10g> select username,tablespace,session_num sid,sqladdr,sqlhash,segtype,extents,blocks from v$sort_usage;

USERNAME TABLESPACE     SID SQLADDR     SQLHASH SEGTYPE EXTENTS  BLOCKS
-------- ---------- ------- -------- ---------- ------- ------- -------
SEC      TEMP           370 389AEC58 1029988163 DATA          1     128
SEC      TEMP           370 389AEC58 1029988163 INDEX         1     128

可見SEC使用者中建立的臨時表以及其上的索引均存放在TEMP臨時表空間中。
在建立使用者的時候,可以指定使用者的預設臨時表空間,這樣不同使用者在建立臨時表的時候便可以使用各自的臨時表空間,互不干擾。

6.不同的session不可以互相訪問對方的臨時表資料
1)在第一個session中檢視臨時表資料
sec@ora10g> select * from t_temp_session;

         X
----------
         1
         2

此資料為初始化環境時候插入的資料。

2)在單獨開啟一個session,檢視臨時表資料。
ora10g@secdb /home/oracle$ sqlplus sec/sec

SQL*Plus: Release 10.2.0.1.0 - Production on Wed Jun 29 22:30:05 2011

Copyright (c) 1982, 2005, Oracle.  All rights reserved.


Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

sec@ora10g> select * from t_temp_session;

no rows selected

說明不同的session擁有各自獨立的臨時表操作特點,不同的session之間是不能互相訪問資料。

7.臨時表資料將不會上DML(Data Manipulation Language)鎖
1)在新session中檢視SEC使用者下鎖資訊
sec@ora10g> col username for a8
sec@ora10g> select
  2       b.username,
  3       a.sid,
  4       b.serial#,
  5       a.type "lock type",
  6       a.id1,
  7       a.id2,
  8       a.lmode
  9  from v$lock a, v$session b
 10  where a.sid=b.sid and b.username = 'SEC'
 11  order by username,a.sid,serial#,a.type;

no rows selected

不存在任何鎖資訊。

2)向臨時表中插入資料,檢視鎖資訊
(1)插入資料
sec@ora10g> insert into t_temp_session values (1);

1 row created.

(2)檢視鎖資訊
sec@ora10g> select
  2       b.username,
  3       a.sid,
  4       b.serial#,
  5       a.type "lock type",
  6       a.id1,
  7       a.id2,
  8       a.lmode
  9  from v$lock a, v$session b
 10  where a.sid=b.sid and b.username = 'SEC'
 11  order by username,a.sid,serial#,a.type;

                               lock                                lock
USERNAME        SID    SERIAL# type           id1         id2      mode
-------- ---------- ---------- ------ ----------- ----------- ---------
SEC             142        425 TO           12125           1         3
SEC             142        425 TX           65554         446         6

此時出現TO和TX型別鎖。

(3)提交資料後再次檢視鎖資訊
sec@ora10g> commit;

Commit complete.

sec@ora10g> select
  2       b.username,
  3       a.sid,
  4       b.serial#,
  5       a.type "lock type",
  6       a.id1,
  7       a.id2,
  8       a.lmode
  9  from v$lock a, v$session b
 10  where a.sid=b.sid and b.username = 'SEC'
 11  order by username,a.sid,serial#,a.type;

                               lock                                lock
USERNAME        SID    SERIAL# type           id1         id2      mode
-------- ---------- ---------- ------ ----------- ----------- ---------
SEC             142        425 TO           12125           1         3

事務所TX被釋放。TO鎖保留。

3)測試更新資料場景下鎖資訊變化
(1)更新臨時表資料
sec@ora10g> update t_temp_session set x=100;

1 row updated.

(2)鎖資訊如下
                               lock                                lock
USERNAME        SID    SERIAL# type           id1         id2      mode
-------- ---------- ---------- ------ ----------- ----------- ---------
SEC             142        425 TO           12125           1         3
SEC             142        425 TX          524317         464         6

(3)提交資料
sec@ora10g> commit;

Commit complete.

(4)鎖資訊情況
                               lock                                lock
USERNAME        SID    SERIAL# type           id1         id2      mode
-------- ---------- ---------- ------ ----------- ----------- ---------
SEC             142        425 TO           12125           1         3

4)測試刪除資料場景下鎖資訊變化
(1)刪除臨時表資料
sec@ora10g> delete from t_temp_session;

1 row deleted.

(2)檢視鎖資訊
                               lock                                lock
USERNAME        SID    SERIAL# type           id1         id2      mode
-------- ---------- ---------- ------ ----------- ----------- ---------
SEC             142        425 TO           12125           1         3
SEC             142        425 TX          327713         462         6

(3)提交資料
sec@ora10g> commit;

Commit complete.

(4)鎖資訊情況
                               lock                                lock
USERNAME        SID    SERIAL# type           id1         id2      mode
-------- ---------- ---------- ------ ----------- ----------- ---------
SEC             142        425 TO           12125           1         3

5)總結
在臨時表上的增刪改等DML操作都會產生TO鎖和TX事務所。TO鎖會從插入資料開始一直存在。
但整個過程中都不會產生DML的TM級別鎖。

8.小結
  本文就臨時表使用過程中常見的問題和特點進行了介紹。臨時表作為Oracle的資料庫物件,如果能夠在理解這些特性基礎上加以利用將會極大地改善系統效能。

Good luck.

secooler
11.06.29

-- The End --








在Oracle8i或以上版本中,可以建立以下兩種臨時表: 

1。會話特有的臨時表

CREATE GLOBAL TEMPORARY ( ) 
ON COMMIT PRESERVE ROWS; 

2。事務特有的臨時表

CREATE GLOBAL TEMPORARY ( ) 
ON COMMIT DELETE ROWS; 
CREATE GLOBAL TEMPORARY TABLE MyTempTable  

所建的臨時表雖然是存在的,但是你試一下insert 一條記錄然後用別的連線登上去select,記錄是空的,明白了吧,我把下面兩句話再貼一下: 

--ON COMMIT DELETE ROWS 說明臨時表是事務指定,每次提交後ORACLE將截斷表(刪除全部行) 
--ON COMMIT PRESERVE ROWS 說明臨時表是會話指定,當中斷會話時ORACLE將截斷表。 

衝突的問題更本不用考慮.

臨時表只是儲存當前會話(session)用到的資料,資料只在事務或會話期間存在。

通過CREATE GLOBAL TEMPORARY TABLE命令建立一個臨時表,對於事務型別的臨時表, 資料只是在事務期間存在,對於會話型別的臨時表,資料在會話期間存在。

會話的資料對於當前會話私有。每個會話只能看到並修改自己的資料。DML鎖不會加到 臨時表的資料上。下面的語句控制行的存在性。

● ON COMMIT DELETE ROWS 表名行只是在事務期間可見 
● ON COMMIT PRESERVE ROWS 表名行在整個會話期間可見

可以對臨時表建立索引,檢視,出發器,可以用export和import工具匯入匯出表的 定義,但是不能匯出資料。表的定義對所有的會話可見。

Temporary Tables臨時表 

1簡介 

ORACLE資料庫除了可以儲存永久表外,還可以建立臨時表temporary tables。這些臨時表用來儲存一個會話SESSION的資料, 

或者儲存在一個事務中需要的資料。當會話退出或者使用者提交commit和回滾rollback事務的時候,臨時表的資料自動清空, 
但是臨時表的結構以及後設資料還儲存在使用者的資料字典中。 

臨時表只在oracle8i以及以上產品中支援。 

2詳細介紹 

Oracle臨時表分為 會話級臨時表 和 事務級臨時表。 

會話級臨時表是指臨時表中的資料只在會話生命週期之中存在,當使用者退出會話結束的時候,Oracle自動清除臨時表中資料。 
事務級臨時表是指臨時表中的資料只在事務生命週期中存在。當一個事務結束(commit or rollback),Oracle自動清除臨時表中資料。 

臨時表中的資料只對當前Session有效,每個Session都有自己的臨時資料,並且不能訪問其它Session的臨時表中的資料。因此, 

臨時表不需要DML鎖.當一個會話結束(使用者正常退出 使用者不正常退出 ORACLE例項崩潰)或者一個事務結束的時候,Oracle對這個會話的 

表執行 TRUNCATE 語句清空臨時表資料.但不會清空其它會話臨時表中的資料. 

你可以索引臨時表和在臨時表基礎上建立檢視.同樣,建立在臨時表上的索引也是臨時的,也是隻對當前會話或者事務有效. 

臨時表可以擁有觸發器. 

3建立臨時表 

臨時表的定義對所有會話SESSION都是可見的,但是表中的資料只對當前的會話或者事務有效. 

建立方法: 

1) ON COMMIT DELETE ROWS 定義了建立事務級臨時表的方法.

CREATE GLOBAL TEMPORARY TABLE admin_work_area 
(startdate DATE, 
enddate DATE, 
class CHAR(20)) 
ON COMMIT DELETE ROWS; 

EXAMPLE:

SQL> CREATE GLOBAL TEMPORARY TABLE admin_work_area 
 (startdate DATE, 
enddate DATE, 
class CHAR(20)) 
ON COMMIT DELETE ROWS; 
SQL> create table permernate( a number); 
SQL> insert into admin_work_area values(sysdate,sysdate, ‘temperary table ‘); 
SQL> insert into permernate values(1); 
SQL> commit; 
SQL> select * from admin_work_area; 
SQL> select * from permernate; 
A 
1 
 

2)ON COMMIT PRESERVE ROWS 定義了建立會話級臨時表的方法.

CREATE GLOBAL TEMPORARY TABLE admin_work_area 
(startdate DATE, 
enddate DATE, 
class CHAR(20)) 
ON COMMIT PRESERVE ROWS; 
EXAMPLE:

會話1:

SQL> drop table admin_work_area; 
SQL> CREATE GLOBAL TEMPORARY TABLE admin_work_area 
2 (startdate DATE, 
3 enddate DATE, 
4 class CHAR(20)) 
5 ON COMMIT PRESERVE ROWS; 
SQL> insert into permernate values(2); 
SQL> insert into admin_work_area values(sysdate,sysdate, ‘session temperary ‘); 
SQL> commit; 
SQL> select * from permernate;

A 
---------- 
1 
2

SQL> select * from admin_work_area;

STARTDATE ENDDATE CLASS 
---------- ---------- -------------------- 
17-1?? -03 17-1?? -03 session temperary

會話2:

SQL> select * from permernate;

A 
---------- 
1 
2

SQL> select * from admin_work_area;

未選擇行.

會話2看不見會話1中臨時表的資料.

4 ORACLE臨時表和SQLSERVER臨時表異同

SQL SERVER臨時表

也可以建立臨時表。臨時表與永久表相似,但臨時表儲存在 tempdb 中,當不再使用時會自動刪除。 
有本地和全域性兩種型別的臨時表,二者在名稱、可見性和可用性上均不相同。本地臨時表的名稱以單個數字符號 (#) 打頭; 
它們僅對當前的使用者連線是可見的;當使用者從 Microsoft? SQL Server? 2000 例項斷開連線時被刪除。全域性臨時表的名稱以數學符號 

(##) 打頭,建立後對任何使用者都是可見的,當所有引用該表的使用者從 SQL Server 斷開連線時被刪除。 
例如,如果建立名為 employees 的表,則任何人只要在資料庫中有使用該表的安全許可權就可以使用該表,除非它已刪除。 
如果建立名為 #employees 的本地臨時表,只有您能對該表執行操作且在斷開連線時該表刪除。如果建立名為 ##employees 的全域性臨時表 

資料表中的任何使用者均可對該表執行操作。如果該表在您建立後沒有其他使用者使用,則當您斷開連線時該表刪除。如果該表在您建立 

後有其他使用者使用,則 SQL Server在所有使用者斷開連線後刪除該表 

不同: 

1. SQL SERVER臨時表是一種”記憶體表”,表是儲存在記憶體中的.ORACLE臨時表除非執行DROP TABLE,否則表定義會保留在資料字典中. 

2. SQL SERVER臨時表不存在類似ORACLE臨時表 事務級別 上的功能. 

3 SQL SERVER本地臨時表(#) 與 ORACLE的會話級別臨時表類似,但是在會話退出的時候,ORACLE不會刪除表. 

4 SQL SERVER的全域性臨時表(##) 是指多個連線共享同一片記憶體.當沒有指標引用該記憶體區域時,SQL SERVER自動釋放全域性臨時表. 

5 由於ORACLE不是一種 記憶體中的資料庫. 所以如果ORACLE類似SQL SERVER 頻繁的對臨時表進行建立和刪除,必定會影響效能. 
所以ORACLE會保留臨時表的定義直到使用者DROP TABLE. 

6 在ORACLE中,如果需要多個使用者共享一個表(類似SQL SERVER的全域性臨時表##).則可以利用永久表, 

並且在表中新增一些可以唯一標識使用者的列.利用觸發器和檢視.當使用者退出的時候,根據該登陸使用者的唯一資訊刪除相應的表中的資料. 

這種方法給ORACLE帶來了一定量的負載.




我們都知道,全域性臨時表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');






About Me

...............................................................................................................................

● 本文作者:小麥苗,只專注於資料庫的技術,更注重技術的運用

● 本文在itpub(http://blog.itpub.net/26736162)、部落格園(http://www.cnblogs.com/lhrbest)和個人微信公眾號(xiaomaimiaolhr)上有同步更新

● 本文itpub地址:http://blog.itpub.net/26736162/abstract/1/

● 本文部落格園地址:http://www.cnblogs.com/lhrbest

● 本文pdf版及小麥苗雲盤地址:http://blog.itpub.net/26736162/viewspace-1624453/

● 資料庫筆試面試題庫及解答:http://blog.itpub.net/26736162/viewspace-2134706/

● QQ群:230161599     微信群:私聊

● 聯絡我請加QQ好友(646634621),註明新增緣由

● 於 2017-06-02 09:00 ~ 2017-06-30 22:00 在魔都完成

● 文章內容來源於小麥苗的學習筆記,部分整理自網路,若有侵權或不當之處還請諒解

● 版權所有,歡迎分享本文,轉載請保留出處

...............................................................................................................................

拿起手機使用微信客戶端掃描下邊的左邊圖片來關注小麥苗的微信公眾號:xiaomaimiaolhr,掃描右邊的二維碼加入小麥苗的QQ群,學習最實用的資料庫技術。

Oracle全域性臨時表
DBA筆試面試講解
歡迎與我聯絡

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

相關文章