性能測試之數(shù)據(jù)庫調(diào)優(yōu)篇(轉(zhuǎn)-請作者與我聯(lián)系)
前言:
通過緊張的網(wǎng)通、移動性能測試,雖然測試準備和討論的環(huán)節(jié)很多,應用服務器測試如果要體現(xiàn)應用服務器的性能,那么在測試環(huán)節(jié)中,其他環(huán)節(jié)不能成為瓶頸,否則應用服務器的性能將很難展現(xiàn)。但實際在我們的測試實踐中,無論準備情況,數(shù)據(jù)庫調(diào)優(yōu)都是永恒的話題,數(shù)據(jù)庫的優(yōu)劣直接影響整個測試的性能表現(xiàn)。本文結(jié)合了一些測試經(jīng)驗和一些資料的整理,給出了個人的一些經(jīng)驗,共大家分享,本文測重于 Unix 環(huán)境。
一般問題的發(fā)現(xiàn)及解決:
Oracle 數(shù)據(jù)庫服務器是整個系統(tǒng)的核心,它的性能高低直接影響整個系統(tǒng)的性能,為了調(diào)整 Oracle 數(shù)據(jù)庫服務器的性能,主要從以下幾個方面考慮:
第一步:
??? 調(diào)整操作系統(tǒng)以適合 Oracle 數(shù)據(jù)庫服務器運行, Oracle 數(shù)據(jù)庫服務器很大程度上依賴于運行服務器的操作系統(tǒng),如果操作系統(tǒng)不能提供最好性能,那么無論如何調(diào)整, Oracle 數(shù)據(jù)庫服務器也無法發(fā)揮其應有的性能。
第二步:
? ?? 為 Oracle 數(shù)據(jù)庫服務器規(guī)劃系統(tǒng)資源,據(jù)已有計算機可用資源 ,? 規(guī)劃分配給 Oracle 服務器資源原則是:盡可能使 Oracle 服務器使用資源最大化 , 特別在 Client/Server 中盡量讓服務器上所有資源都來運行 Oracle 服務。調(diào)整計算機系統(tǒng)中的內(nèi)存配置,多數(shù)操作系統(tǒng)都用虛存來模擬計算機上更大的內(nèi)存,它實際上是硬盤上的一定的磁盤空間。當實際的內(nèi)存空間不能滿足應用軟件的要求時,操作系統(tǒng)就將用這部分的磁盤空間對內(nèi)存中的信息進行頁面替換,這將引起大量的磁盤 I/O 操作,使整個服務器的性能下降。為了避免過多地使用虛存,應加大計算機的內(nèi)存。
第三步:
??? 為 Oracle 數(shù)據(jù)庫服務器設(shè)置操作系統(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)先級運行。
第四步:
? ?? 調(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 、庫緩沖區(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)存量。
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)存量。
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 可設(shè)置分配緩沖區(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ù)庫后才能使新的設(shè)置起作用。
IO 問題的發(fā)現(xiàn)及解決:
很多的時侯,當應用很慢、數(shù)據(jù)庫很慢的時侯,我們到數(shù)據(jù)庫時做幾個示例的 Select 也發(fā)現(xiàn)同樣的問題時,有些時侯我們會無從下手,因為我們認為數(shù)據(jù)庫的各種命種率都是滿足 Oracle 文檔的建議。實際上如今的優(yōu)化己經(jīng)向優(yōu)化等待 (waits) 轉(zhuǎn)型了,實際中性能優(yōu)化最根本的出現(xiàn)點也都集中在 IO ,這是影響性能最主要的方面,由系統(tǒng)中的等待去發(fā)現(xiàn) Oracle 庫中的不足、操作系統(tǒng)某些資源利用的不合理是一個比較好的辦法。在移動的測試中, Sun 的工程師也推薦這樣的做法。
第一步:
通過操作系統(tǒng)的一些工具檢查系統(tǒng)的狀態(tài),比如 CPU 、內(nèi)存、交換、磁盤的利用率,根據(jù)經(jīng)驗或與系統(tǒng)正常時的狀態(tài)相比對,有時系統(tǒng)表面上看起來看空閑這也可能不是一個正常的狀態(tài),因為 cpu 可能正等待 IO 的完成。除此之外我們還應觀注那些占用系統(tǒng)資源 (cpu 、內(nèi)存 ) 的進程。
1 、如何檢查操作系統(tǒng)是否存在 IO 的問題?使用的工具有 sar, 這是一個比較通用的工具。
Rp1#sar -u 2 10
即每隔 2 秒檢察一次,共執(zhí)行 20 次。示例返回:
Linux
10:36:07 AM CPU %user %nice %system %idle
10:36:09 AM all 0.00 0.00 0.13 99.87
10:36:11 AM all 0.00 0.00 0.00 100.00
10:36:13 AM all 0.25 0.00 0.25 99.49
10:36:15 AM all 0.13 0.00 0.13 99.75
10:36:17 AM all 0.00 0.00 0.00 100.00
10:36:17 AM CPU %user %nice %system %idle
10:36:19 AM all 0.00 0.00 0.00 100.00
10:36:21 AM all 0.00 0.00 0.00 100.00
10:36:23 AM all 0.00 0.00 0.00 100.00
10:36:25 AM all 0.00 0.00 0.00 100.00
其中的 %usr 指的是用戶進程使用的 cpu 資源的百分比, %sys 指的是系統(tǒng)資源使用 cpu 資源的百分比, %wio 指的是等待 io 完成的百分比,這是值得我們觀注的一項, %idle 即空閑的百分比。如果 wio 列的值很大,如在 35% 以上,說明你的系統(tǒng)的 IO 存在瓶頸,你的 CPU 花費了很大的時間去等待 IO 的完成。 Idle 很小說明系統(tǒng) CPU 很忙。
當你的系統(tǒng)存在 IO 的問題,可以從以下幾個方面解決
1 、查找 Oracle 中不合理的 sql 語句,對其進行優(yōu)化。
2 、對 Oracle 中訪問量頻繁的表除合理建索引外,再就是把這些表分表空間存放以免訪問上產(chǎn)生熱點,再有就是對表合理分區(qū)。
第二步:
關(guān)注一下內(nèi)存,常用的工具便是 vmstat ,對于 hp-unix 來說可以用 glance,Aix 來說可以用 topas, 當你發(fā)現(xiàn) vmstat 中 pi 列非零, memory 中的 free 列的值很小, glance,topas 中內(nèi)存的利用率多于 80% 時,這時說明你的內(nèi)存方面應該調(diào)節(jié)一下了,方法大體有以下幾項。
1 、劃給 Oracle 使用的內(nèi)存不要超過系統(tǒng)內(nèi)存的 1/2, 一般保在系統(tǒng)內(nèi)存的 40% 為益。
為系統(tǒng)增加內(nèi)存
2 、如果你的連接特別多,可以使用 MTS 的方式
3 、打全補丁,防止內(nèi)存漏洞。
第三步:
如何找到點用系用資源特別大的 Oracle 的 session 及其執(zhí)行的語句。 Hp-unix 可以用 glance,top ; IBM AIX 可以用 topas ;此外可以使用 ps 的命令。通過這些程序我們可以找到占用系統(tǒng)資源特別大的這些進程的進程號,我們就可以通過以下的 sql 語句發(fā)現(xiàn)這個 pid 正在執(zhí)行哪個 sql ,這個 sql 最好在 pl/sql developer,toad 等軟件中執(zhí)行 , 把 <> 中的 spid 換成你的 spid 就可以了。
SELECT a.username,a.machine,a.program,a.sid,a.serial#,a.status,c.piece,c.sql_text from v$session a,v$process b,v$sqltext c WHERE b.spid='<>' AND b.addr=a.paddr AND a.sql_address=c.address(+)order BY c.piece
我們就可以把得到的這個 sql 分析一下,看一下它的執(zhí)行計劃是否走索引,對其優(yōu)化避免全表掃描,以減少 IO 等待,從而加快語句的執(zhí)行速度。
另一個有用的腳本:查找前十條性能差的 sql:
SELECT * FROM (select PARSING_USER_ID,EXECUTIONS,SORTS,COMMAND_TYPE,DISK_READS,sql_text FROM v$sqlarea
order BY disk_reads DESC )where ROWNUM<10 ;
注意:在做優(yōu)化
sql
時,經(jīng)常碰到使用
in
的語句,這時我們一定要用
exists
把它給換掉,因為
Oracle
在處理
In
時是按
Or
的方式做的,即使使用了索引也會很慢。
(
這個很有用,我在煙草項目中,大量的
not in
操作對大數(shù)據(jù)量的查詢是相當?shù)穆臑?/span>
exists
后,性能提高
100
倍左右,視圖中的數(shù)量級為百萬
)
總結(jié)
在性能測試中應當指出,由于客戶機、網(wǎng)絡、服務器這 3 個相互依存的組成部分都必須調(diào)整和同步才能產(chǎn)生最佳的性能,因此還應根據(jù)系統(tǒng)的具體情況,具體分析和調(diào)整。本文涉及的 Oracle 調(diào)優(yōu)是數(shù)據(jù)庫調(diào)優(yōu)的一小部分,希望同事們不斷的補充我們的知識庫。