Oracle資料庫中大型表查詢優化研究

2021-08-24 19:32:03 字數 4426 閱讀 4298

摘 要:對海量資料進行訪問查詢時,常常遇到系統響應時間過長,占用系統資源過多的問題。本文結合例項著重對oracle資料庫中的查詢優化進行了研究,測試結果表明採用的方法是很有效的,大大縮短了測試用例表的響應時間,最後對海量資料的優化方法提出了實用性的建議。

1 引 言

在***飛行地面資料處理平台中,需要查詢歷史飛行資料來進行飛行狀態的模擬及其飛行事故的分析,從而對當前飛機狀態進行評判。其資料量非常巨大。如何對其進行快速訪問,提高系統響應時間就顯得十分重要。在實際應用中,往往採用各種優化措施,使得sql查詢經過資料庫優化器的處理,得到最佳的執行計畫,即資料訪問路徑,來達到提高響應速度的目的。由於專案採用的是oracle資料庫,以下考慮對oracle資料庫進行的優化情況。

2 oracle查詢順序及其調整

oracle優化的一般順序如下:環境調整(伺服器、網路、磁碟)、oracle例項調整、oracle物件調整、oracle sql調整。我們的測試採用的oracle資料表容量為50 m,記錄條數為50萬條。測試方法為:根據使用者的查詢要求計算得到使用者需要瀏覽的資料記錄的起止位置,然後在sql語句中加入此位置,執行sql語句,查詢該資料表,得到使用者想要瀏覽的記錄集合。使 用的sql語句如下:

select*from(select*from(select*from big)

where rownum<topos order byrownum desc)where rownum<toposfrompos+1;

使用該sql查詢得到結果集需要5~6 s,這個響應速度難以滿足使用者瀏覽要求,因此必須對其優化以提高響應速度。我們是在假定環境調整已經完成的條件下通過對oracle例項、物件、sql查詢語句的調整得出結論的,其中重點是對sql語句的調整

2.1 例項調整

首先進行oracle例項調整。oracle例項涉及到sga記憶體區和一組oracle後台處理程序。對oracle例項的調整就是對sga記憶體區和oracle後台處理程序的調整。在對該問題的解決中,主要是針對sga記憶體區的調整。

2.1.1 sga記憶體區結構

sga就是系統全域性區,是指記憶體中允許多個程序相互通訊的區域。在oracle中,sga對所有程序來說都是全域性的可用的。圖1為sga結構圖。

緩衝區快取記憶體是sga中為所有使用者和系統程序儲存資料的區域,任何資料在傳遞給乙個呼叫的應域是共享的,所以多個程序可以從這片快取記憶體讀取同樣的資料塊,而不必每次都從物理磁碟中讀取。

[img]

共享池是sga中的另乙個區域,其中儲存著關於待執行的sql語句的資訊。他由兩部分組成:資料字典快取記憶體,存放從資料字典中讀取的資訊以用於處理sql請求;庫快取記憶體,存放需要執行的sql語句資訊,包括每個sql語句的語法分析樹和執行計畫。如果多個使用者要執行同樣的sql語句,那麼語法分析樹和執行計畫就可以重複利用,省去了語法分析步驟的昂貴花費。

2.1.2 調整sga結構

一般來講,在系統硬體支援的情況下,系統全域性區越大越有利於資料庫高效的執行。大的緩衝區快取記憶體可以快取更多的資料塊,這樣可以提高快取命中率,節省物理磁碟讀取的高昂代價;大的共享池意味著大的庫快取記憶體。庫快取的記憶體結構如圖2所示。

[img]

庫快取越大,可以儲存的sql語法分析資訊越多;此外,資料庫中的一些物件,如表、索引、過程、觸發器、軟體包等也在首次執行後進駐庫快取記憶體。大的庫快取可以保證對這些物件的高命中率,從而節省解析和載入代價。

作為乙個通用的優化原則,我們在解決該問題時,適當增大了sga的容量,從而保證oracle例項可以比較高效的執行。設定緩衝區快取記憶體的容量為32 m,設定共享池的大小為56 m。執行rpt_lib.sql程式檢查庫快取記憶體不足率(還沒有執行該指令碼),表明庫快取足夠。

2.2 物件調整

這一步驟我們要對每乙個oracle物件進行調整從 而優化效能,包括對所有的儲存引數進行正確的設定,尤其是對影響輸入輸出的引數進行設定。pctfree,pctused,freelist引數的設定都會對sql效能產生重要影響。

在解決該問題時,我們沒有對物件的儲存引數進行調整。物件的儲存引數的調整要建立在具體物件的基礎之上,我們使用的測試大表除了在容量上模擬可能的實際物件之外,和實際物件並沒有多少可比之處。舉例來說,pctfree引數是指在實際的儲存塊中,留出來為塊中的記錄擴充套件所用的空閒空間占該儲存塊容量的百分比,這個引數和實際表記錄的長度及可擴充套件性有關,要在設計出實際表之後進行調整。因此我們對物件的儲存引數使用了資料庫的預設設定。資料庫的物件還包括索引、過程、包等,對物件的調整要包括對他們的調整,這裡一併略去。

2.3 sql語句調整

sql語言是一種靈活的語言,相同的功能可以使用不同的語句來實現,但是語句的執行效率是很不相同,一般考慮如下規則:

(1)新增索引

在對大表進行掃瞄時,首先要避免不必要的全表掃瞄。最通常的做法就是給大表新增索引。所謂全表掃瞄,就是在訪問表時,從磁碟上儲存該錶的起始位置開始逐記錄讀資料,直到該錶的結束位置。給大表新增索引後,我們可以通過訪問索引的方式獲得記錄的物理位置,從而達到訪問表的目的。設想一下,對於乙個擁有大量欄位的表,如果只需要返回其中少量字段,那麼在這些欄位上建立索引,通過索引訪問獲得記錄,將大大降低物理磁碟讀寫次數,從而降低了整個查詢響應時間(事實上,這種情況下根本沒有必要訪問資料表,只是訪問索引就足夠了)。在我們的測試用表中,只有4個字段,顯然無法發揮索引的這一優勢。我們的測試用表的特點是記錄條數多,達到50萬條,但每次返回的記錄數只有幾十條,在這種情況下,使用索引同樣可以起到好的效果。首先在檢索條件上建立索引,在表訪問時,我們通過索引來獲取目的記錄集的實體地址,因為返回的記錄數不多,所以這種方式造成的物理讀寫很少,應該可以獲得較滿意的訪問時間。在測試中,我們對測試用表的條件字段新增索引,但事實上並沒有提高查詢的響應時間,這是因為在sql語句的執行計畫中,在新增索引之前和之後,oracle生成的執行計畫中,表訪問方式都是全表掃瞄,根本沒有使用我們新增的索引。那麼此時我們可以採用新增提示的方法。

(2)新增提示

在oracle中,我們可以在sql語句中加入提示,來影響oracle對優化模式的選擇,從而生成最優的執行計畫。於是我們在sql語句中加入提示,強制優化器在生成執行計畫時將表的訪問方式從全表掃瞄改為索引範圍掃瞄。結果該查詢花費了比全表掃瞄多得多的響應時間。仔細檢視這個sql語句的執行計畫,我們發現oracle對這個索引進行了全索引掃瞄,這樣造成的物理讀寫數量比起全表掃瞄不僅沒有減少,反而大幅上公升。尋找原因,問題出在我們索引的字段上。我們索引的age欄位為了測試方便,每條記錄的值都不相同,這樣的字段其實並不具備建立索引的條件。在該測試中,我們首先要將索引載入記憶體,由於索引各不相同,oracle採取了全索引掃瞄的方式訪問索引,我們要讀取的是30萬條記錄(age>200 k),通過索引,我們獲得的將是30萬個記錄的rowid,如果這些記錄在磁碟上的物理位置沒有按索引順序排序,那麼我們就不得不通過30萬個rowid來訪問這些記錄,這樣造成的物理讀寫是相當驚人的,這就是為什麼我們使用了索引,卻反而查詢速度更慢的原因所在。事實上oracle的優化器選擇全表訪問是已經對不同的執行計畫作過比較的了。同時,這裡同樣違背了乙個oracle優化的準則,對於沒有按索引順序排序的表,如果檢索記錄數小於總記錄數的7%,用索引比全表掃瞄快。

(3)更改優化器模式

優化器是oracle資料庫中接受來自產生器處理過的sql語句的程式。他將對sql進行優化,生成內部執行計畫,這個計畫是oracle訪問物理磁碟資料的路徑。根據優化器模式的不同,生成的內部執行計畫也不同,而對於相同的sql,永遠只有乙個最優的執行計畫,因此選擇合適的優化器模式,是很重要的。oracle有2種優化器模式:基於規則的優化模式和基於成本的優化模式。在這次測試中,我們使用的優化器模式引數為choose,這樣oracle將根據sql語句相關表索引的有無,統計資料的有無以及sql語句中的提示,自動判斷使用哪種優化模式。

(4)將調整持久化

oracle的執行計畫是根據各種情況,比如表的統計資料變化的,但有時這種變化是我們不希望的。為了將我們已經調整好的sql執行計畫固定,我們可以 用oracle的工具將執行計畫持久化儲存。

2.4 調整結果

通過對這個測試用例的調整,我們最終將此大表的響應時間從5 s縮短到不足2 s。經過調整後的緩衝區快取記憶體達到113 m,大約佔物理記憶體的50%,調整後的sql語句為:

select name,age,memo from

(selectname,age,memo,rownum asmynum from test2)

wheremynum>400000 and mynum<=400010;

我們測試所用的機器配置為celetron500 m,記憶體256 m,硬碟為ide8.4 g。可以說是執行oracle8i的最低配置。啟動oracle 8i資料庫後,記憶體使用達到300 m以上,也就是說已經在用虛擬記憶體;測試開始後,cpu保持或接近滿載,這些都會影響oracle的效能表現,也會影響測試結果。

3 結 語

以下幾點可以作為通用的oracle sql調整原則:

(1)消除不必要的全表掃瞄,可以通過新增索引達到。

(2)快取小型表的全表掃瞄,可以通過將小型表置入緩衝區快取記憶體的keep池中實現。

(3)如果表有多個索引,要保證oracle正在使用對此sql最優化的索引,可以通過新增提示實現。

oracle資料庫員工表查詢

孟子辰 2016 11 28 10 13 1 請從表emp中查詢工種是職員clerk或經理manager的雇員姓名 工資。select ename,sal from emp where job clerk or job manager 2 請在emp表中查詢部門號在10 30之間的雇員的姓名 部門號...

oracle 資料庫表結構查詢

oracle查詢使用者所有表的語句 select from all tab comments 查詢所有使用者的表,檢視等 select from user tab comments 查詢本使用者的表,檢視等 select from all col comments 查詢所有使用者的表的列名和注釋.s...

資料庫 oracle查詢表資訊

修改資料庫中一張表指定欄位的資料,該字段在其他表中也存在,需要同步修改 此時需要統計資料庫中所有包含該字段的表。獲取表字段 select from user tab columns where table name 使用者表 獲取表注釋 select from user tab comments w...