2009-12-09 154 views
1

我試圖將存儲過程中使用的永久錶轉換爲全局臨時表。我查看了這些永久表上的統計信息,其中一些數據有數千萬行數據,並且在大小爲千兆字節(高達10 GB)時處於訂單狀態。Oracle 10g臨時表

所以,

CREATE TABLE my_table ( 
    column1 NUMBER, 
    column2 NUMBER, 
    etc... 
) 
TABLESPACE BIGTABLESPACE 
NOLOGGING 
NOCOMPRESS 
NOCACHE 
NOPARALLEL 
MONITORING; 

應該成爲

CREATE GLOBAL TEMPORARY TABLE my_table ( 
    column1 NUMBER, 
    column2 NUMBER, 
    etc.. 
) 
ON COMMIT PRESERVE ROWS; 

我創建與應予以保留,直到每個現有的永久表中的會話結束行等效全局臨時表。這個全局臨時表將在過程中使用,而不是永久表。
EXECUTE IMMEDIATE 'TRUNCATE ...'在開始和INSERT /*+ APPEND */ INTO在稍後的某個點)

所有永久表都在一個大的表空間中創建BIGTABLESPACE

的全局臨時表將在被創建的Oracle文檔狀態用戶的臨時表空間(我認爲這是TEMP)。與此問題是TEMP表空間很小,並且範圍未設置爲在過程中增長到我需要它們增長的大小。

TEMP表空間數據庫創建

create database "$oracle\_sid" 
    user sys identified by "$sys\_password" 
    user system identified by "$system\_password" 
    set default bigfile tablespace 
    controlfile reuse 
    maxdatafiles 256 
    maxinstances $maxinstances 
    maxlogfiles 16 
    maxlogmembers 3 
    maxloghistory 1600 
    noarchivelog 
    character set WE8MSWIN1252 
    national character set AL16UTF16 
    datafile 
     '$oracle\_home/oradata/$oracle\_sid/system01.dbf' size 512M 
    logfile 
     '$oracle\_home/oradata/$oracle\_sid/redo01.log' size 1G, 
     '$oracle\_home/oradata/$oracle\_sid/redo02.log' size 1G, 
     '$oracle\_home/oradata/$oracle\_sid/redo03.log' size 1G 
    sysaux datafile 
     '$oracle\_home/oradata/$oracle\_sid/sysaux01.dbf' size 256M 
    default temporary tablespace temp tempfile 
     '$oracle\_home/oradata/$oracle\_sid/temp01.dbf' size 5G 
    undo tablespace "UNDOTBS1" datafile 
     '$oracle\_home/oradata/$oracle\_sid/undotbs01.dbf' size 5G; 

永久表中創建(即我打算替換)表中的最初創建BIGTABLESPACE

-- 50G bigfile datafile size 
create bigfile tablespace "BIGTABLESPACE" 
datafile '$oracle\_home/oradata/$oracle\_sid/bts01.dbf' size 50G 
extent management local 
segment space management auto; 

永久表的索引是最初創建於表空間BIGTABLESPACE

-- 20G bigfile datafile size 
create bigfile tablespace "BIGINDXSPACE" 
datafile '$oracle\_home/oradata/$oracle\_sid/btsindx01.dbf' size 20G 
extent management local 
segment space management auto; 
  • 用全局臨時表替換這些永久表是否可行?
  • TEMP表空間將遇到擴展TEMP表空間的問題。有沒有辦法在表空間BIGTABLESPACEBIGINDXSPACE中創建全局臨時表及其索引?
  • 如果不是,我如何才能使TEMP表空間像大文件表空間那樣工作並實現索引/表分隔?
  • 我可以創建兩個TEMP bigfile表空間並將索引創建爲一個表並將表創建爲另一個表?

我想使用全局臨時表,但我在過程中處理的數據量似乎高於並超出了全局臨時表的設計。 有什麼建議嗎?

回答

4

將數據和索引分隔到單獨的表空間中除了可能使DBA更舒服地將相似的對象組合在一起之外沒有任何好處。有一個長期以來的觀點認爲,分離索引和數據對於性能原因是有利的 - 這是不正確的。

臨時對象應該(也必須)存儲在臨時表空間中。如果您想將這些大的臨時表分隔到單獨的表空間中,您可以增加TEMP表空間的大小,或者爲將擁有這些對象的用戶創建一個單獨的臨時表空間。你不能(也不想)將它們存儲在永久表空間中。

雖然在體系結構上,我會非常好奇你的系統中爲什麼需要臨時表。如果您的會話將10 GB的數據寫入臨時表,那麼爲了將數據寫入其他地方,大概再次讀取這10個GB的數據,我傾向於懷疑存在更有效的解決方案。 Oracle甚至需要臨時表是非常罕見的 - 在其他數據庫中,讀者可以阻止編寫者在處理之前需要將數據從表中複製出來的情況非常罕見。 Oracle沒有這樣的限制。

+0

這就是爲什麼臨時表是必要的: 我正在使用的Oracle數據庫有一個指定用戶,擁有所有權限,所有權限。客戶端預留SQL應用程序 用於以此用戶身份登錄並開始會話,在此期間可調用任何存儲過程。這些存儲過程使用永久表。我不希望一個會話的過程運行與另一個會話重疊,並且重疊 - 雙向插入數據到存儲過程中使用的永久表中。 – 2009-12-09 17:35:05

+0

但爲什麼存儲過程首先將任何瞬態數據寫入表?特別是10個GB的瞬態數據。這是最令人困惑的設計的組成部分。如果數據沒有被永久寫入,那麼大概你可以只寫一個查詢來對照底層表來獲取你程序需要的任何數據。 – 2009-12-09 19:16:01

+0

由於複雜性,瞬態數據被寫入表中。 從多個永久源表中收集數據,然後進行處理(連接,過濾,計算),最終結果爲 附加到多個結果表(永久性)。 加入我的意思是外部,內部或笛卡爾需要。 通過過濾我的意思是WHERE子句條件。 通過計算我的意思是選擇計算/函數調用。 這是一個複雜的多步驟過程,最好在聲明式SQL中處理。 SQL適用於簡單。另外還有 剩下的數據用於調試。 – 2009-12-09 20:22:45

0

我查看了大型全球臨時表進行遷移練習。它的工作,但調試和拒絕had I我最終與普通表一起去。

如果GTT不能解決問題,請考慮行級安全/ VPD(甚至視圖)。 您可以有一個從sys_context('USERENV','SESSIONID')派生的列,並使用它來確保用戶只能看到他們自己的數據。

多個會話同時處理多千兆字節數據集的想法仍然有點可怕。

PS。我相信對於通過過程使用的GTT,使用會話用戶的臨時表空間而不是過程所有者的臨時表空間。如果您可以將會話作爲單獨的oracle用戶獲得,那麼您有機會將文件IO分散到不同的表空間中。

1

我不認爲你的描述中有任何東西讓GTT變得沒有吸引力。您顯然需要非常大的臨時表空間,但除非您大量使用表壓縮(在GTT中至少高達10gR2不可用),否則不會佔用更多空間。考慮使用表空間組:http://download.oracle.com/docs/cd/B19306_01/server.102/b14231/tspaces.htm#ADMIN01103

使用表空間組,而不是單一的臨時表空間,可以緩解導致的問題,其中一個表空間不足以容納一個排序結果,尤其是對具有表許多分區。表空間組使並行執行服務器在單個並行操作中可以使用多個臨時表空間。

此外,不要忽視使用子查詢保理條款。他們通常可以替代使用臨時表。但是,他們可能仍然需要儘可能多的臨時存儲空間,因爲來自SQFC的大型結果集可能會溢出到磁盤以避免消耗太多內存,因此您仍然需要繼續增加TEMP空間。它們非常方便,無需在每次需要新的臨時表時部署新的數據庫對象。