調(diào)整Oracle應用系統(tǒng)性能的原則和方法
Oracle 數(shù)據(jù)庫廣泛應用在社會的各個領(lǐng)域,特別是在Client/Server模式的應用,但是應用開發(fā)者往往碰到整個系統(tǒng)的性能隨著數(shù)據(jù)量的增大顯著下降的問題,為了解決這個問題,從以下幾個方面:數(shù)據(jù)庫服務器、網(wǎng)絡I/O、應用程序等對整個系統(tǒng)加以調(diào)整,充分發(fā)揮Oracle的效能,提高整個系統(tǒng)的性能。很多用戶在選購數(shù)據(jù)庫時都***Oracle數(shù)據(jù)庫,調(diào)整Oracle數(shù)據(jù)庫應用系統(tǒng)時應該遵從一定的原則,下文中將為大家講解調(diào)整Oracle數(shù)據(jù)庫應用系統(tǒng)性能的原則和方法。
1 調(diào)整數(shù)據(jù)庫服務器的性能
Oracle數(shù)據(jù)庫服務器是整個系統(tǒng)的核心,它的性能高低直接影響整個系統(tǒng)的性能,為了調(diào)整Oracle數(shù)據(jù)庫服務器的性能,主要從以下幾個方面考慮:
1.1 調(diào)整操作系統(tǒng)以適合Oracle數(shù)據(jù)庫服務器運行
Oracle數(shù)據(jù)庫服務器很大程度上依賴于運行服務器的操作系統(tǒng),如果操作系統(tǒng)不能提供***性能,那么無論如何調(diào)整,Oracle數(shù)據(jù)庫服務器也無法發(fā)揮其應有的性能。
1.1.1 為Oracle數(shù)據(jù)庫服務器規(guī)劃系統(tǒng)資源
據(jù)已有計算機可用資源, 規(guī)劃分配給Oracle服務器資源原則是:盡可能使Oracle服務器使用資源***化,特別在Client/Server中盡量讓服務器上所有資源都來運行Oracle服務。
1.1.2 調(diào)整計算機系統(tǒng)中的內(nèi)存配置
多數(shù)操作系統(tǒng)都用虛存來模擬計算機上更大的內(nèi)存,它實際上是硬盤上的一定的磁盤空間。當實際的內(nèi)存空間不能滿足應用軟件的要求時,操作系統(tǒng)就將用這部分的磁盤空間對內(nèi)存中的信息進行頁面替換,這將引起大量的磁盤I/O操作,使整個服務器的性能下降。為了避免過多地使用虛存,應加大計算機的內(nèi)存。
1.1.3 為Oracle數(shù)據(jù)庫服務器設置操作系統(tǒng)進程優(yōu)先級
不要在操作系統(tǒng)中調(diào)整Oracle進程的優(yōu)先級,因為在Oracle數(shù)據(jù)庫系統(tǒng)中,所有的后臺和前臺數(shù)據(jù)庫服務器進程執(zhí)行的是同等重要的工作,需要同等的優(yōu)先級。所以在安裝時,讓所有的數(shù)據(jù)庫服務器進程都使用缺省的優(yōu)先級運行。
1.2 調(diào)整內(nèi)存分配
Oracle數(shù)據(jù)庫服務器保留3個基本的內(nèi)存高速緩存,分別對應3種不同類型的數(shù)據(jù):庫高速緩存,字典高速緩存和緩沖區(qū)高速緩存。庫高速緩存和字典高速緩存一起構(gòu)成共享池,共享池再加上緩沖區(qū)高速緩存便構(gòu)成了系統(tǒng)全程區(qū)(SGA)。SGA是對數(shù)據(jù)庫數(shù)據(jù)進行快速訪問的一個系統(tǒng)全程區(qū),若SGA本身需要頻繁地進行釋放、分配,則不能達到快速訪問數(shù)據(jù)的目的,因此應把SGA放在主存中,不要放在虛擬內(nèi)存中。內(nèi)存的調(diào)整主要是指調(diào)整組成SGA的內(nèi)存結(jié)構(gòu)的大小來提高系統(tǒng)性能,由于Oracle數(shù)據(jù)庫服務器的內(nèi)存結(jié)構(gòu)需求與應用密切相關(guān),所以內(nèi)存結(jié)構(gòu)的調(diào)整應在磁盤I/O調(diào)整之前進行。
1.2.1 庫緩沖區(qū)的調(diào)整
庫緩沖區(qū)中包含私用和共享SQL和PL/SQL區(qū),通過比較庫緩沖區(qū)的命中率決定它的大小。要調(diào)整庫緩沖區(qū),必須首先了解該庫緩沖區(qū)的活動情況,庫緩沖區(qū)的活動統(tǒng)計信息保留在動態(tài)性能表v$librarycache數(shù)據(jù)字典中,可通過查詢該表來了解其活動情況,以決定如何調(diào)整。
Select sum(pins),sum(reloads) from v$librarycache;
Pins列給出SQL語句,PL/SQL塊及被訪問對象定義的總次數(shù);Reloads列給出SQL 和PL/SQL塊的隱式分析或?qū)ο蠖x重裝載時在庫程序緩沖區(qū)中發(fā)生的錯誤。如果sum(pins)/sum(reloads) ≈0,則庫緩沖區(qū)的命中率合適;若sum(pins)/sum(reloads)>1, 則需調(diào)整初始化參數(shù) shared_pool_size來重新調(diào)整分配給共享池的內(nèi)存量。
1.2.2 數(shù)據(jù)字典緩沖區(qū)的調(diào)整
數(shù)據(jù)字典緩沖區(qū)包含了有關(guān)數(shù)據(jù)庫的結(jié)構(gòu)、用戶、實體信息。數(shù)據(jù)字典的命中率,對系統(tǒng)性能影響極大。數(shù)據(jù)字典緩沖區(qū)的使用情況記錄在動態(tài)性能表v$librarycache中,可通過查詢該表來了解其活動情況,以決定如何調(diào)整。
Select sum(gets),sum(getmisses) from v$rowcache;
Gets列是對相應項請求次數(shù)的統(tǒng)計;Getmisses 列是引起緩沖區(qū)出錯的數(shù)據(jù)的請求次數(shù)。對于頻繁訪問的數(shù)據(jù)字典緩沖區(qū),sum(getmisses)/sum(gets)<10%~15%。若大于此百分數(shù),則應考慮增加數(shù)據(jù)字典緩沖區(qū)的容量,即需調(diào)整初始化參數(shù)shared_pool_size來重新調(diào)整分配給共享池的內(nèi)存量。
1.2.3 緩沖區(qū)高速緩存的調(diào)整
用戶進程所存取的所有數(shù)據(jù)都是經(jīng)過緩沖區(qū)高速緩存來存取,所以該部分的命中率,對性能至關(guān)重要。緩沖區(qū)高速緩存的使用情況記錄在動態(tài)性能表v$sysstat中,可通過查詢該表來了解其活動情況,以決定如何調(diào)整。
Select name,value from v$sysstat where name in
('dbblock gets','consistent gets','physical reads');
dbblock gets和consistent gets的值是請求數(shù)據(jù)緩沖區(qū)中讀的總次數(shù)。physical reads的值是請求數(shù)據(jù)時引起從盤中讀文件的次數(shù)。從緩沖區(qū)高速緩存中讀的可能性的高低稱為緩沖區(qū)的命中率,計算公式:
Hit Ratio=1-(physical reds/(dbblock gets+consistent gets))
如果Hit Ratio<60%~70%,則應增大db_block_buffers的參數(shù)值。db_block_buffers可以調(diào)整分配給緩沖區(qū)高速緩存的內(nèi)存量,即db_block_buffers可設置分配緩沖區(qū)高速緩存的數(shù)據(jù)塊的個數(shù)。緩沖區(qū)高速緩存的總字節(jié)數(shù)=db_block_buffers的值*db_block_size的值。db_block_size 的值表示數(shù)據(jù)塊大小的字節(jié)數(shù),可查詢 v$parameter 表:
select name,value from v$parameter where name='db_block_size';
在修改了上述數(shù)據(jù)庫的初始化參數(shù)以后,必須先關(guān)閉數(shù)據(jù)庫,在重新啟動數(shù)據(jù)庫后才能使新的設置起作用。
1.3 調(diào)整磁盤 I/O
磁盤的I/O速度對整個系統(tǒng)性能有重要影響。解決好磁盤I/O問題,可顯著提高性能。影響磁盤I/O的性能的主要原因有磁盤競爭、I/O次數(shù)過多和數(shù)據(jù)塊空間的分配管理。
為Oracle數(shù)據(jù)庫服務器創(chuàng)建新文件時,不論是表空間所用的數(shù)據(jù)文件還是數(shù)據(jù)事務登錄所用的日志文件,都應仔細考慮數(shù)據(jù)庫服務器上的可用磁盤資源。如果服務器上有多個磁盤,則可將文件分散存儲到各個可用磁盤上,減少對數(shù)據(jù)庫的數(shù)據(jù)文件及事務日志文件的競爭,從而有效地改善服務器的性能。對于不同的應用系統(tǒng)都有各自的數(shù)據(jù)集,應當創(chuàng)見不同的表空間分別存儲各自應用系統(tǒng)的數(shù)據(jù),并且盡可能的把表空間對應的數(shù)據(jù)文件存放在不同的磁盤上,這種從物理上把每個應用系統(tǒng)的表空間分散存放的方法,可以排除兩個應用系統(tǒng)競爭磁盤的可能性。數(shù)據(jù)文件、事務日志文件分別存放在不同的磁盤上,這樣事務處理執(zhí)行的磁盤訪問不妨礙對相應的事物日志登記的磁盤訪問。如果有多個磁盤可用,將兩個事物日志成員放在不同的磁盤驅(qū)動器上,就可以消除日志文件可能產(chǎn)生的磁盤競爭。應把一個應用的表數(shù)據(jù)和索引數(shù)據(jù)分散存放不同表空間上,并且盡量把不同類型的表空間存放在不同磁盤上,這樣就消除了表數(shù)據(jù)和索引數(shù)據(jù)的磁盤競爭。
1.4 調(diào)整數(shù)據(jù)庫服務器的回滾段
回滾段是一個存儲區(qū)域,數(shù)據(jù)庫使用該存儲區(qū)域存放曾經(jīng)由一個事務更新或刪除的行的原始數(shù)據(jù)值。如果用戶要回滾一個事務所做的改變,那么數(shù)據(jù)庫就從回滾段中讀回改變前的數(shù)據(jù)并使該事務影響的行改變?yōu)樗鼈兊脑瓲顟B(tài)?;貪L段控制著數(shù)據(jù)庫處理事務的能力,因而在數(shù)據(jù)庫成功中起著關(guān)鍵性的作用,不管數(shù)據(jù)庫的其它部分設計得多好,如果它設計得不合理,將會嚴重影響系統(tǒng)的性能。建立和調(diào)整回滾段的原則如下。
1.4.1 分離回滾段
分離回滾段是指單獨為回滾段創(chuàng)建一個以上的表空間,使回滾段與數(shù)據(jù)字典、用戶數(shù)據(jù)、索引等分離開來。由于回滾段的寫入與數(shù)據(jù)和索引的寫入是并行進行的,因此將它分離出來可以減少I/O爭用。如果回滾段與數(shù)據(jù)不分離,倘若要某個表空間脫機或撤消,那么在該表空間中的各個回滾段沒有全部脫機之前,不能將這個表空間脫機或撤消。而一旦該表空間不可用,則該表空間中的所有回滾段也不能使用,這將浪費所有分配的磁盤空間。所以,獨立回滾段可使數(shù)據(jù)庫管理變得容易。回滾段的經(jīng)常性收縮,使得表空間的自由塊更容易形成碎片。分離回滾段可以減少數(shù)據(jù)庫表空間的碎片產(chǎn)生。
1.4.2 創(chuàng)建不同大小的回滾段群
對于一些聯(lián)機事物處理,他們一般是頻繁地對少量數(shù)據(jù)進行修改,創(chuàng)建許多小的回滾段對之有利。每一個事物的入口項只能限于一個回滾段,回滾段應該充分大以容納一個完整的事物處理,因此對一些較大型事物,需要較大型的回滾段。極個別脫機處理事物會產(chǎn)生大量的回滾信息,這時需要一個特大號的回滾段來處理。根據(jù)這些理論,在Oracle數(shù)據(jù)庫服務器中針對上述3種事物處理創(chuàng)建三組:小事物組、較大事物組、特大事物組等大小不同的回滾段群,并且將之分散到3個不同的表空間上,群內(nèi)大小相同,應能滿足該組事物處理的***要求。
1.4.3 創(chuàng)建數(shù)量適當?shù)幕貪L段
一般回滾段數(shù)量與并發(fā)事物個數(shù)有關(guān),以下給出由于并發(fā)事物個數(shù)而應建立回滾段的參考數(shù):
并發(fā)事物(n) 回滾段數(shù)
n<16 4
16 ≤ n<32 8
n≥ 32 n/4
2 調(diào)整 Client/Server 模式下的網(wǎng)絡 I/O
Client/Server環(huán)境中的應用處理是分布在客戶應用程序和數(shù)據(jù)庫服務程序之間的。在 Client/Server環(huán)境中Client與Server之間的網(wǎng)絡I/O是整個系統(tǒng)性能提高的瓶頸,一個客戶應用程序引起的網(wǎng)絡I/O越少,應用及整個系統(tǒng)的性能越好。減少網(wǎng)絡I/O的最重要的一條原則:將應用邏輯集中在數(shù)據(jù)庫服務器中。
2.1 使用Oracle數(shù)據(jù)庫的完整約束性
當為應用建表時,應當為一些有特殊要求的數(shù)據(jù)加上適當?shù)耐暾约s束,這樣就能實現(xiàn)由數(shù)據(jù)庫本身而不是應用程序來約束數(shù)據(jù)符合一定的條件。數(shù)據(jù)庫服務器端的完整約束的執(zhí)行操作是在比SQL語句級別更低的系統(tǒng)機制上優(yōu)化,它與客戶端無關(guān),只在服務器中運行,不需在Client 端和Server端之間傳遞SQL語句,有效地減輕網(wǎng)絡I/O負擔。
2.2 使用數(shù)據(jù)庫觸發(fā)器
完整約束性只能實現(xiàn)一些較簡單的數(shù)據(jù)約束條件,對一些較復雜的事物處理規(guī)則就無能為力,這時***不要在應用程序中實施復雜的程序控制,而是應當采用數(shù)據(jù)庫觸發(fā)器來實施復雜的事物規(guī)則。數(shù)據(jù)庫觸發(fā)器能實現(xiàn)由數(shù)據(jù)庫本身,而不是應用程序,來約束數(shù)據(jù)符合復雜的事物處理規(guī)則,并且容易創(chuàng)建,便于管理,避免大量的網(wǎng)絡I/O。
例如:將當前表A中成為歷史的記錄從A表中轉(zhuǎn)儲到歷史表B中,表示為Lsbs。
在應用程序中實現(xiàn): 用數(shù)據(jù)庫觸發(fā)器實現(xiàn):
Beign Create trigger delete1
Update A set lsbs='T'; After update of lsbs on A
Insert into B For each row
Select * from A where lsbs='T'; Insert into B
Delete A where lsbs='T'; select * from A where :new.lsbs='T';
End; Delete A where :new.lsbs='T';
End delete1;
在應用程序中實現(xiàn)時,所有的SQL命令請求傳送的數(shù)據(jù)都要通過網(wǎng)絡在Client端和Server端進行交換,而不像數(shù)據(jù)庫觸發(fā)器一樣,SQL本身在Server端,不需要通過網(wǎng)絡傳輸數(shù)據(jù)。當進行操作的數(shù)據(jù)量相當大時,并且多個用戶同時操作時,通過在應用程序中實現(xiàn)復雜的控制,必將增大網(wǎng)絡I/O的負荷,使整個系統(tǒng)的性能降低,而用數(shù)據(jù)庫觸發(fā)器能完全避免這種情況發(fā)生。
2.3 使用存儲過程、存儲函數(shù)和包
Oracle的存儲過程和存儲函數(shù)是命名的能完成一定功能并且存儲在Server端的PL/SQL的集合。包是一種把有關(guān)的過程和函數(shù)組織封裝成一個數(shù)據(jù)庫程序單元的方法。它們相對于應用程序的過程、函數(shù)而言,把SQL命令存儲在Server端。使用存儲過程和存儲函數(shù),應用程序不必再包含多個網(wǎng)絡操作的SQL語句去執(zhí)行數(shù)據(jù)庫服務器操作,而是簡單調(diào)用存儲過程和存儲函數(shù),在網(wǎng)絡上傳輸?shù)闹皇钦{(diào)用過程的名字和輸出結(jié)果,這樣就可減少大量的網(wǎng)絡I/O。
例如:基表A、B的定義:name char(20);detail char(10);A表100萬記錄,應用程序?qū)幕鞟中檢索detail列符合給出條件的記錄,并將之插入基表B。
Declare
Cursor cursor1 is select*from A;poin cursor1%type;
con1 number(2);res1 char(4)='abcd';
Begin Insert into B values(poin.name,poin.detail);end if;
For poin in cursor1 loop End loop;End loop;
For con1 in 1..7 loop Commit;
If substr(poin.detail ,con1,4)=res1 then End;
如果在Developer/2000 From中按鈕觸發(fā)器直接用PL/SQL實現(xiàn)和把它改寫為一個Oracle存儲過程,然后在From中調(diào)用此過程實現(xiàn)比較,后者性能顯著提高。
在考慮使用上述3種方法時:首先考慮使用完整約束性。對于數(shù)據(jù)庫觸發(fā)器和存儲過程,如果需要所有訪問數(shù)據(jù)庫的程序自動實施一定規(guī)則或檢查,那么使用數(shù)據(jù)庫觸發(fā)器;如果只需對少數(shù)的程序?qū)嵤┮欢ǖ囊?guī)則或檢查,則可創(chuàng)建一個過程,讓有關(guān)程序調(diào)用這個過程。
3 應用程序的調(diào)整
3.1 SQL語句的優(yōu)化
SQL語句的執(zhí)行速度,可以受很多因素的影響而變化。但主要的影響因素是:驅(qū)動表、執(zhí)行操作的先后順序和索引的運用。可以由很多不同的方法間接地改變這些因素,以達到***的執(zhí)行速度。這里主要探討當對多個表進行連接查詢時應遵循的優(yōu)化原則:
(1) 用于連接的子句的列應被索引、在Where子句中應盡量利用索引,而不是避開索引。
(2) 連接操作應從返回較少行上驅(qū)動。
(3) 如果所連接的表A和B,A表長度遠遠大于B表,建議從較大的A表上驅(qū)動。
(4) 如果Where子句中含有選擇性條件,Where No=20,將***有選擇性部分放在表達式***。
(5) 如果只有一個表有索引,另一表無索引,無索引的表通常作為驅(qū)動表。如A表的No列以被索引,而B表的No 列沒被索引,則應當B表作為驅(qū)動表,A表作為被驅(qū)動表。
(6) 若用于連接的列和Where子句中其他選擇條件列均有索引,則按各個索引對查詢的有效性和選擇性分別定出級別,結(jié)合表中具體數(shù)據(jù)構(gòu)成情況,從中選出優(yōu)化路徑,一般需要考慮:子句中哪些列可以使用索引、哪些索引具有唯一性及被查詢表行數(shù)目等。
3.2 建立和使用視圖、索引
利用視圖可以將基表中的列或行進行裁減、隱藏一部分數(shù)據(jù),并且能夠?qū)⑸婕暗蕉鄠€表的復雜查詢以視圖的方式給出,使應用程序開發(fā)簡潔快速。利用索引可以提高查詢性能,減少磁盤 I/O,優(yōu)化對數(shù)據(jù)表的查詢,加速SQL語句的執(zhí)行。但任何時候建立索引都能提高性能,何時建立索引應當遵循以下原則:該表常用來在索引列上查詢,該表不常更新、插入、刪除等操作,查詢出來的結(jié)果記錄數(shù)應控制在原表的2%~4%。
3.3 使用 Oracle 的數(shù)組接口
當一個客戶應用程序插入一行或用一個查詢來向服務器請求某行時,不是發(fā)送具有單個行的網(wǎng)絡包,而是采用數(shù)組處理,即把要插入的多個行或檢索出的多個行緩沖在數(shù)組中,然后通過很少的幾個包就可在網(wǎng)上傳送這些數(shù)組。例如,一個給定的Select語句返回2000行數(shù)據(jù),每行平均大小為40個字節(jié),數(shù)據(jù)包的大小為4kB,而數(shù)組大小參數(shù)(arraysize)設置為20 ,則需從服務器發(fā)送100個數(shù)據(jù)包到客戶機。如果簡單地把(arraysize)設置為2000,那么同樣的操作只需要傳送 20個數(shù)據(jù)包。這樣就減少了網(wǎng)絡的傳輸量,提高了所有應用的性能。
總結(jié):我們在開發(fā)應用程序時,遵循上述的方法和原則,對系統(tǒng)進行調(diào)整,收到了令人滿意的效果。但是應當指出,由于客戶機、網(wǎng)絡、服務器這3個相互依存的組成部分都必須調(diào)整和同步才能產(chǎn)生***的性能,因此還應根據(jù)系統(tǒng)的具體情況,具體分析和調(diào)整。