當建立同Oracle會話時,會在服務器內存中劃分出一個專門用來排序的區域,從而為會話提供排序空間。但是,這個排序空間畢竟有限,若記錄數量超過這個排序空間的話,就需要進行磁盤排序。但是,我們都知道,磁盤排序的執行速度要比內存排序的執行速度慢1400倍。而且,磁盤排序會消耗臨時表空間的資源,並且可能影響到正在進行的其他SQL排序,因為Oracle必須為臨時表空間中的數據塊分配緩沖池。而且,過多的磁盤排序會導致空閒緩沖等待,以及將執行其他任務的數據塊從緩沖池中分頁出去。對於數據庫管理員來說,在內存中進行排序總是比磁盤排序更受歡迎。所以說,磁盤排序是影響Oracle數據庫性能的罪魁禍首。在數據庫優化的時候,我們應該想法設法降低數據庫的磁盤排序。為此,筆者有如下建議。
一、合理設置Sort_area_size參數
雖然說Oracle10G以後的數據庫會自動對內存進行管理。但是,在一些性能要求比較高或者排序頻率比較高的數據庫中,仍然有必要對一些影響內存分配的參數進行調整。其中,最重要的一個參數就是Sort_area_size。
Oracle數據庫會為所有的鏈接Oracle會話分配Sort_area_size這個參數。所以,對於擁有大量用戶的數據庫來說,如果增加這個參數的值,會讓磁盤排序的幾率明顯降低,不過數據庫也要為此付出這個代價,很容易導致內存過載。但是,如果這個參數的值設置的過低的話,又會導致過多的磁盤排序。所以,這個參數並不是越大越好。因為這個參數如果設置的過大的話,其帶來的性能收益反而會降低。因為為了提高有限幾個查詢的速度,可能會浪費大量的內存。這無疑是我們數據庫管理員不希望看到的。
在實際工作中,我們往往需要在兩者之間進行一個均衡。設置一個合理的參數,盡量讓數據庫減少磁盤排序的幾率,同時也不能使得服務器內存過載。為此筆者有一個建議。數據庫管理員應該每隔一段時間增加這個參數的值,並使用Statspack工具定時監控內存排序與磁盤排序的數據。在起初進行調整的時候最好每個小時查詢一次。通過這些數據,我們就可以得到一個合理的參數值,在兩這之間取得一個均衡。
前期調整完成後,在後期仍然需要進行監控。因為後期隨著企業應用的改變,這個參數仍然需要根據實際情況進行調整,以提高數據庫的性能
二、盡量減少不必要的磁盤排序
在某些情況下,盡管數據庫管理員沒有直接通過Order By等語句對數據庫記錄進行排序,可是Oracle數據庫服務器仍然會對查詢結果進行排序。因為這些語句需要起作用,必須要先對數據進行排序。所以,他們往往帶有隱性的排序功能。
我們在數據庫維護或者前台應用程序設計的時候,要盡量的減少這種不必要的排序。如Distinct關鍵字,它的作用就是取消重復的記錄。但是,要實現這個目的的話,則數據庫必須要先對記錄進行排序,然後才能夠去除重復的記錄內容。故在設計的時候,盡量要避免使用Distinct關鍵字。其實,筆者在工作中,經常會碰到這種情況,某些記錄其實不存在重復記錄,但是程序開發人員為了保障數據的准確性,就在SQL語句中加入了Distinct關鍵字,從而造成了不必要的排序。
另外,在其他一些情況下,也會導致不必要的排序。如排序合並連接,也會導致不必要的排序。故無論何時,只要使用了排序合並連接,就會執行排序已連接關鍵值。故在數據庫與應用程序設計的時候,要盡量避免排序合並連接。其實,在許多情況下,嵌套循環連接反而使更好的選擇。因為這個嵌套循環連接,它更加有效而且不會導致不必要的排序以及不比要的全表掃描。
其次,有時候缺失索引也會導致一些並不要的排序。故數據庫管理員在平時的工作中,要盡量的減少這些不必要的排序,以讓寶貴的內存資源交給更重要的任務來適用,提高Oracle數據庫性能。
三、利用Statspack工具監控排序活動
Statspack工具是一款提高Oracle數據庫性能的很好的輔助工具。因為它可以幫助我們收集很多有用的信息。故我們數據庫管理員也可以利Statspack工具對數據庫中的排序活動進行監控。
對於一個有經驗的數據庫管理員來說,對內存排序和磁盤排序保持必要的排需是非常必要的。因為我們無法左右用戶的行為;而用戶的行為又會有所調整。用戶在調整的過程中,有可能又會增加額外的磁盤排序。當然,也有可能磁盤排序的幾率會減少。但是,通常情況下,隨著用戶交易數據的增加,這個磁盤排序的幾率在理論上仍然是往上爬的。而實際上也是往上升的,只是這個升的速度沒有理論上那麼快而已。這主要是看數據庫管理員如何進行管理了。
根據筆者的了解,企業用戶的操作往往會有一個周期性的變化,如按年或者按月進行周期性的變化。數據庫管理員應該養成一個好習慣,每個月利用Statspack工具定期的對數據庫進行監控。特別是要監控數據庫的排序情況。Statspack工具還有額外的一個功能,就是自動監測與警告功能。也就是說,可以讓Statspack這個工具在磁盤排序數量超過一個預設置的閥值時,自動給數據庫管理員發送一個警告,如通過郵件形式發送給管理員等等。筆者通過監控發現,每到月底與月初的時候,磁盤排序的數量會大大的增加。這主要是因為在月底的時候,用戶會對當月的交易數據進行統計。所以當月底月初的時候,由於交易記錄比較多,所以,會有比較多的磁盤排序發生。在這種情況下,數據庫管理員有必要對相關參數進行調整。不過這個調整是暫時的調整,等到這個周期過去後,仍然要把參數調回來。只有如此,數據庫的整體性能才會有所保障。即不會因為內存過載而降低數據庫性能;也不會因為磁盤排序而給數據庫造成額外的負擔。
所以,雖然排序是SQL語句執行中 很微小的一個部分,但是其對數據庫性能影響卻比較大,而且也是非常顯著的。可惜的是,排序是SQL調整中往往被忽視的地方。在Oracle數據庫中,排序對用戶來說是透明的。也就是說,排序對用戶很少有所限制,用戶可以根據自己的需要來對數據進行隨意地排序。但是,用戶並不知道,什麼樣的操作會降低數據庫的性能。故如何降低用戶的不合理操作而產生額外的排序,甚至是磁盤排序,這是數據庫管理員在平時工作中必須要考慮到的一個問題。通過以上三個方法,或許可以給數據庫管理員找到一些解決問題的思路。相信通過以上方法,可以最大程度的減少磁盤排序的發生,不再讓磁盤排序成為影響數據庫性能的罪魁禍首。