目前全部使用Oracle做爲數據庫支撐平臺的應用,大部分是數據量比較龐大的系統,即表的數據量級通常狀況下都是在百萬級以上。固然,在Oracle中建立分區是一種不錯的選擇,可是當發現應用有多張表關聯的時候,而且這些表大部分都比較龐大,而關聯的時候發現其中的某一張或者某幾張表關聯以後獲得的結果集很是小,而且查詢獲得這個結果集的速度很是快,那麼這個時候考慮在Oracle中建立「臨時表」。sql
在建立數據表的時候,若是沒有特殊地指明,那麼建立的表是一個永久的關係型表,也就是說,這個表中對應的數據,除非是顯式地刪除,不然表中的數據是永遠都存在的。相對應的,在Oracle數據庫中,還有一種類型的表,叫作臨時表。這個臨時表跟永久表最大的區別就是表中的數據不會永遠地存在。當一個會話結束或者事務結束的時候,這個臨時表中的數據,不用用戶本身刪除,數據庫本身會自動清除。數據庫
Oracle的臨時表建立以後基本不佔用表空間,若是沒有指定臨時表(包括臨時表的索引)存放的表空間,那麼插入到臨時表的數據是存放在Oracle系統的默認臨時表空間中(TEMP),一個系統可能有多個臨時表空間。臨時表的數據只能存放在臨時表空間中。安全
臨時表的數據只是在事務期間存在,對於會話類型的臨時表,數據在會話期間存在,會話的數據對於當前會話私有,每一個會話只能看到並修改本身的數據。DML鎖不會加到臨時表的數據上。能夠對臨時表建立索引、視圖、觸發器,能夠用exp和imp工具導入導出表的定義,可是不能導出數據。session
(一)臨時表的特色併發
l 多用戶操做的獨立性:對於使用同一張臨時表的不一樣用戶,Oracle都會分配一個獨立的TEMP SEGMENT,這樣就避免了多個用戶在對同一張臨時表操做時發生交叉,從而保證了多個用戶操做的併發性和獨立性。oracle
l 數據的臨時性:既然是臨時表,顧名思義,存放在該表中的數據是臨時性的。Oracle根據建立臨時表時指定的參數(ON COMMIT DELETE ROWS /ON COMMIT PRESERVE ROWS),自動將數據TRUNCATE掉。ide
(二)臨時表的分類工具
Oracle數據庫根據臨時表的性質不一樣,能夠分爲事務臨時表(ON COMMIT DELETE ROWS)與會話臨時表(ON COMMIT PRESERVE ROWS)。性能
一、事務臨時表測試
事務臨時表是指數據只有在當前事務內有效,該臨時表與事務相關,當進行事務提交或者事務回滾的時候,臨時表中的數據將自動被清空,其它的內容和會話級的臨時表的一致(包括退出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後,當前會話就看不到數據了。
二、會話臨時表
會話臨時表,顧名思義,是指數據只在當前會話內是有效的臨時表。關閉當前會話或者進行新的鏈接以後,數據表中的內容就會被清除。
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_STATS在SCHEMA級別收集,須要設置GATHER_TEMP爲TRUE(默認爲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)
因此,對於臨時表儘可能使用動態採樣,而不該該收集它的統計信息。由於統計信息被全部會話所共享,而全局臨時表的數據是與會話相關的,不一樣的會話其含有的數據量是不一樣的。
真題一、 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.)
A、It stores only the temporary table but not its indexes.
B、It stores both the temporary table as well as its indexes.
C、It must be a nondefault temporary tablespace for the database.
D、It can be a default or nondefault temporary tablespace for the database.
E、It must be the default temporary tablespace of the user who issues the command.
答案:B、D。
本題中的命令是在TBS_T1表空間中建立了一個事務臨時表ADMIN_WORK_AREA,而且在該臨時表上建立了一個索引,最後要求選出有關TBS_T1表空間的2個正確的選項。
本題中,對於選項A,TBS_T1表空間只存數據而不存索引,說法錯誤,應該都存儲。因此,選項A錯誤。
對於選項B,TBS_T1表空間即存儲數據也存儲索引,說法正確。因此,選項B正確。
對於選項C,TBS_T1表空間必須是非默認的表空間,說法錯誤,默認和非默認均可以。因此,選項C錯誤。
對於選項D,TBS_T1表空間能夠是一個默認或非默認的數據庫的臨時表空間。因此,選項D正確。
對於選項E,TBS_T1表空間必須是默認的表空間,說法錯誤,默認和非默認均可以。因此,選項E錯誤。
因此,本題的答案爲B、D。
臨時表(Tempotary table)用於保存事務或會話期間的中間結果集。臨時表中保存的數據只對當前會話可見,全部會話都看不到其餘會話的數據;即便當前會話已經提交了(commit)數據,別的會話也看不到它的數據。對於臨時表,不存在多用戶併發的問題,由於一個會話不會由於使用一個臨時表而阻塞另外一個會話。即便咱們「鎖住」了臨時表,也不會妨礙其餘會話使用臨時表。
臨時表比常規表生成的redo少得多。不過因爲臨時表必須爲其中包含的數據生成undo信息,因此也會生成必定的redo。update和delete會生成最多的undo,insert和select生成的undo最少。
臨時表會從當前登陸用戶的臨時表空間分配存儲空間,或者若是從一個定義者權限過程訪問臨時表,就會使用該過程全部者的臨時表空間。全局臨時表其實是表自己的一個模板。建立臨時表的動做不涉及存儲空間分配,不會爲此初始區段,這與常規表有所不一樣。對於臨時表,運行時當一個會話第一次在臨時表中放入數據時,纔會爲該會話建立一個臨時段。因爲每一個回話會獲得其本身的臨時段(而不是一個現有段的一個區段),每一個用戶可能在不一樣的表空間爲其看in是表分配空間。USER1的臨時表空間可能設置爲TEMP1,所以他的臨時表會從這個表空間分配。USER2可能把TEMP2做爲其臨時表空間,它的臨時表就會從那裏分配。
Oracle的臨時表與其餘關係數據庫中的臨時表相似,主要區別是:Oracle的臨時表是「靜態」定義的。每一個數據庫只建立一次臨時表,而不是爲數據庫中的每一個存儲過程都建立一次。在Oracle歷史表必定存在,他們做爲對象放在數據字典中,可是在會話向臨時表中放入數據以前,臨時表看上去老是空的。因爲臨時表是靜態定義的,因此你能建立引用臨時表的視圖,還能夠建立存儲過程只用靜態SQL來引用臨時表,等等。
臨時表能夠是會話的(臨時表中的數據能夠跨提交存在,即提交以前仍然存在,可是斷開鏈接後再鏈接時數據就沒有了),也能夠是基於事務的(提交以後數據就消失)。語法以下:
基於會話的臨時表,在會話斷開以前,或者經過一個delete或truncate物理地刪除行以前,這些行會一直存在於這個臨時表中。只有個人會話能看到這些行,即便我已經提交,其餘會話也沒法看到個人行。
基於事務的臨時表,個人會話提交時,臨時表中的行就不見了。只需把分配給這個表的臨時區段交回,這些行就會消失,在臨時表的自動清除過程當中不存在開銷。
臨時表能夠有永久表的許多屬性。他們能夠有觸發器,檢查約束,索引等。但永久表的某些特性在臨時表中並不支持,這包括如下特性。
在全部數據庫中,臨時表的缺點之一就是優化器不能正常地獲得臨時表的真實統計信息。使用基於代價的優化器(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');