在Oracle數據庫中進行排序、分組匯總、索引等到作時,會產生很多的臨時數據。如有一張員工信息表,數據庫中是安裝記錄建立的時間來保存的。如果用戶查詢時,使用Order BY排序語句指定按員工編號來排序,那麼排序後產生的所有記錄就是臨時數據。對於這些臨時數據,Oracle數據庫是如何處理的呢?
通常情況下,Oracle數據庫會先將這些臨時數據存放到內存的PGA(程序全局區)內。在這個程序全局區中有一個叫做排序區的地方,專門用來存放這些因為排序操作而產生的臨時數據。但是這個分區的容量是有限的。當這個分區的大小不足以容納排序後所產生的記錄時,數據庫系統就會將臨時數據存放到臨時表空間中。這就是臨時表空間的來歷。看起來好像這個臨時表空間是個臨時工,對於數據庫的影響不會有多大。其實大家這是誤解這個臨時表空間了。在用戶進行數據庫操作時,排序、分組匯總、索引這些作業是少不了,其會產生大量的臨時數據。為此基本上每個數據庫都需要用到臨時表空間。而如果這個臨時表空間設置不當的話,則會給數據庫性能帶來很大的負面影響。為此管理員在維護這個臨時表空間的時候,不能夠掉以輕心。要避免因為臨時表空間設置不當影響數據庫的性能。具體來說,主要需要注意如下幾個方面的內容。
一、創建用戶時要記得為用戶創建臨時表空間。 最好在創建用戶時為用戶指定臨時表空間。如可以利用語句default temporary table space語句來為數據庫設置默認的臨時表空間。不過在Oracle數據庫中這個不是強制的。但是筆者強烈建議這麼做。因為如果沒有為用戶指定默認臨時表空間的話,那麼當這個用戶因為排序等操作需要使用到臨時表空間的話,數據庫系統就會“自作聰明”的利用系統表空間SYSTEM來創建臨時段。眾所周知,這是一個系統表空間。由於在這個表空間中存放著系統運行相關的數據,一般的建議是用戶的數據不能夠保存在這個表空間中。那麼如果將用戶的臨時表空間防止在這個系統表空間之內,會產生什麼負面影響呢?
由於臨時表空間中的數據是臨時的。為此數據庫系統需要頻繁的分配和釋放臨時段。這些頻繁的操作會在系統表空間中產生大量的存儲碎片。當這些存儲碎片比較多時,就會影響系統讀取硬盤的效率,從而影響數據庫的性能。其次系統表空間的大小往往是有限制的。此時臨時段也來插一腳,就會占用系統表空間的大小。
為此數據庫管理員需要注意一點,當沒有為用戶指定臨時表空間時,用戶排序等操作仍然需要用到臨時段。此時數據庫系統就會將臨時段放入到系統表空間中。為此就會對數據庫的性能產生不利的影響。所以筆者建議各位讀者與數據庫管理員,在創建用戶的時候同時為用戶指定一個默認的表空間,以減少臨時段對系統表空間的占用。
二、合理設置PGA,減少臨時表空間使用的幾率。 當排序操作產生臨時數據時,數據庫並不是馬上將其存儲在臨時表空間中。通常情況下,會先將這些臨時數據存儲在內存的PGA程序全局區內。只有當這個程序全局區無法容納全部數據時,數據庫系統才會啟用臨時表空間中的臨時段來保存這些數據。但是眾所周知,操作系統從內存中讀取數據要比從硬盤中讀取數據塊幾千倍。為此比較理想的情況是,這個程序全局區足夠的大,可以容納所有的臨時數據。此時數據庫系統就永遠用不到臨時表空間了。從而可以提高數據庫的性能。
但是這畢竟只是一個理想。由於內存大小等多方面的限制,這個PGA程序區的大小往往是有限制的。所以在進行一些大型的排序操作時,這個臨時表空間仍然少不了。現在數據庫管理員可以做的就是合理設置這個PGA程序全局區的大小,盡量減少臨時表空間使用的幾率。如在實際工作中,數據庫管理員可以根據需要來設置初始化參數SORT_AREA_SIZE參數。這個參數主要控制這個PGA程序全局區內排序區的大小。通常情況下,如果這個數據庫系統主要用來查詢並且需要大量的排序、分組匯總、索引等操作時,那麼可以適當調整這個參數,來擴大PGA分區的大小。相反,如果這個系統主要用於更新操作,或者在這個數據庫服務器上還部署由其他的應用程序,那麼這個PGA分區就不能夠占用太多的內存,以防止對其他應用程序產生不利的影響。所以說,數據庫官員不能夠一刀切,需要根據實際情況來調整。在必要的情況下,可以增加系統內存來增加PGA分區的大小,從而降低臨時表空間的使用幾率,以提高數據庫的排序、分組匯總等操作的性能。
總之,如果臨時段被頻繁使用的話,由於內存與硬盤在性能上的差異,從而會降低數據庫的性能。為此在平時工作中,數據庫管理員還需要監控臨時表空間的使用情況,以判斷是否需要采取措施來減少臨時表空間的使用來提高數據庫的查詢性能。為了實現這個目的,筆者建議數據庫管理員可以查看 v$sort_segment這張動態性能視圖。通過這張動態性能視圖可以查看系統排序段(臨時段的一種)的使用情況。另外通過動態性能視圖 v$sort_usage還可以查詢使用排序段的用戶與會話信息。從而為數據庫管理員優化數據庫性能提供數據上的支持。對於這個排序段,筆者還要說明一點。對於排序段來說,同一個例程的所有SQL語句(如果需要排序操作的話)都將共享同一個排序段。並且排序段在第一次需要用到時被創建。排序完成後這個排序段不會被釋放,只有在這個歷程關閉後排序段才會被釋放。為此以上兩張視圖要綜合起來分析,才能夠得到數據庫管理員想要的信息。
三、要為臨時表空間保留足夠的硬盤空間。 其他表空間對應的數據文件,在其創建時就會被完全分配和初始化,即在其創建時就會被分配存儲空間。但是臨時表空間對應的臨時文件則不同。如在 Linux操作系統中,臨時表空間創建時系統是不會分配和初始化臨時文件的。也就是說,不會為臨時文件分配存儲空間。只有臨時數據出現需要用到臨時文件的時候,系統才會在硬盤上分配一塊地方用來保存臨時文件。此時就可能會產生一個問題,即當需要用到臨時文件系統為其分配空間的時候,才會先系統分區中沒有足夠的存儲空間了。此時就會產生一些難以預料的後果。