對于負(fù)載偏重點不同,我們可以簡單的將數(shù)據(jù)庫系統(tǒng)分為CPU負(fù)載系統(tǒng)(CPU Bound System)和IO負(fù)載系統(tǒng)(IO Bound System)。顧名思義,CPU負(fù)載系統(tǒng)的資源瓶頸在于CPU,而IO負(fù)載系統(tǒng)的瓶頸在于磁盤IO。
我們可以通過操作系統(tǒng)的一些命令來確認(rèn)一個系統(tǒng)是否是存在IO負(fù)載。在UNIX下,可以使用"iostat"或者"sar -d"來看系統(tǒng)的IO情況;在windows下,可以通過系統(tǒng)的性能監(jiān)視器查看,但由于性能監(jiān)控器中看到的IO是靜態(tài)的IO總量信息,并不直觀,因此也可以用本站的TopShow工具來查看實時的IO信息。
在UNIX系統(tǒng)下,發(fā)現(xiàn)CPU IDEL很低并不一定代表這是一個CPU負(fù)載系統(tǒng)。一個IO負(fù)載系統(tǒng)在表面上看CPU的IDEL值也可能很低:
oracle@db01:/export/home/oracle> sar -u 1 10
HP-UX hkhpdv45 B.11.23 U ia64 10/24/07
09:43:05 %usr %sys %wio %idle
09:43:06 43 25 30 1
09:43:07 44 36 19 1
09:43:08 23 27 44 6
09:43:09 12 37 50 1
09:43:10 10 36 51 3
09:43:11 15 34 42 9
09:43:12 18 36 44 3
09:43:13 17 35 46 2
09:43:14 12 32 52 4
09:43:15 12 31 56 1
Average 21 33 43 3
我們可以注意到,實際上WIO是引起CPU IDEL過低的主要原因。WIO是當(dāng)一個進程需要運行或已經(jīng)運行后,因為需要等待IO事件而被阻塞了。事實上CPU是處于IDEL狀態(tài)(在某些系統(tǒng)中,已經(jīng)將WIO取消并歸為IDEL),真正的原因是系統(tǒng)中存在IO瓶頸。
通過iostat或者sar -d我們可以找出存在IO瓶頸的磁盤設(shè)備,如果該磁盤設(shè)備是用于Oracle 數(shù)據(jù)庫存儲文件的,我們可以判斷出是數(shù)據(jù)庫存在IO問題。在windows下,可以通過TopShow來找出哪個進程正在進行大量IO傳輸,如果是Oracle進程,也可以判斷為是數(shù)據(jù)庫存在IO問題。
確認(rèn)系統(tǒng)存在IO問題后,我們就需要定位到底是什么引起的IO問題,該采取什么措施來解決問題。根據(jù)我們前面的介紹,Oracle中存在各種IO,要定位IO,最好的工具是statspack(在10g以后,可以用AWR)。通過statspack report的Top 5 Events,我們可以看到對系統(tǒng)系能影響最大的5個等待event,而不同的IO問題會對應(yīng)不同Event,所以,我們可以根據(jù)這些event采取不同的措施來解決IO問題。下面是一個典型的IO負(fù)載系統(tǒng)的Top 5 Event:
Top 5 Timed Events
~~~~~~~~~~~~~~~~~~ % Total
Event Waits Time (s) Ela Time
-------------------------------------------- ------------ ----------- --------
db file sequential read 70,575,969 344,200 53.34
db file scattered read 11,240,748 163,242 25.30
log file sync 657,241 36,363 5.64
CPU time 35,290 5.47
log file parallel write 833,799 20,767 3.22
可以看到,前兩個時間“db file sequential read”和“db file scattered read”分別占了總等待時間的53.34%和25.30%,而我們前面提到這兩個事件分別是由索引掃面和全表掃面(或快速索引掃面)引起的,因此,能解決索引掃面問題和全表掃面問題就能解決這個系統(tǒng)的IO瓶頸。
IO問題到底對CPU有多大影響呢?我們用以上例子中的數(shù)據(jù)分析一下。從等待時間統(tǒng)計數(shù)據(jù)中,我們看到的是時間在總等待時間中所占的比例。而系統(tǒng)的“總響應(yīng)時間 ”= “等待時間 ”+ “CPU工作時間”(注意,上面Top 5事件中的“CPU Time”不是指CPU的工作時間,而是指CPU的等待時間)。“CPU工作時間”的數(shù)據(jù)我們可以在“Instance Activities Stats for DB”這一分類統(tǒng)計數(shù)據(jù)中找到:
Statistic Total per Second per Trans
--------------------------------- ------------------ -------------- ------------
CPU used by this session 17,136,868 396.7 15.5
先計算出“總等待時間” = 344,200 * 100% / 53.34% = 645,294s
“總響應(yīng)時間” = “總等待時間” + “CPU工作時間”= 645,294 + 17,136,868 = 17,782,162s
我們可以算出“CPU工作時間”、“db file sequential read”和“db file scattered read”分別在“總響應(yīng)時間中所占的比例為:
CPU工作時間 = 17,136,868 / 17,782,162 = 96.4%
“db file sequential read” = 344,200 / 17,782,162 = 1.9%
“db file scattered read” = 163,242 / 17,782,162 = 0.9%
可見,IO事件所引起的等待時間在總響應(yīng)時間所占比例并不大。因此,我們在做系統(tǒng)優(yōu)化之前先分析系統(tǒng)是CPU負(fù)載系統(tǒng)還是IO負(fù)載系統(tǒng)對于我們的優(yōu)化方向和最終的優(yōu)化效果起很大的作用。
以下事件是可能由IO問題引起的等待事件,在IO負(fù)載系統(tǒng)中,我們要特別關(guān)注這些事件:
'db file sequential read'
'db file scattered read'
'db file parallel read'
'direct path read'
'direct path write'
'direct path read (lob)'
'direct path write (lob)'
'control file parallel write'
'control file sequential read'
'control file single write'
'log file parallel write'
'log file sync'
'log file sequential read'
'log file single write'
'switch logfile command'
'log file switch completion'
'log file switch (clearing log file)'
'log file switch (checkpoint incomplete)'
'log switch/archive'
'log file switch (archiving needed)'
'db file parallel write'
'db file single write'
'write complete waits'
'free buffer waits'
下面我們就分別介紹如何解決IO問題。
通過對statspack或者awr報告的分析,我們可以得知是那些IO相關(guān)事件引起的IO問題。針對不同的事件,可以采取不同的分析、處理方法。而有一些通用的方法并不是針對特定的事件的。我們這里先介紹一下這些方法。
一個沒有任何用戶SQL的數(shù)據(jù)庫幾乎不產(chǎn)生任何IO?;旧蠑?shù)據(jù)庫所有的IO都是直接或間接由用戶提交的SQL所導(dǎo)致的。這意味著我們可以通過控制單個SQL產(chǎn)生的IO來降低數(shù)據(jù)庫總的IO請求。而通過SQL調(diào)優(yōu)來降低SQL查詢計劃中的IO操作次數(shù)則是降低SQL產(chǎn)生IO的最好方法。數(shù)據(jù)庫的性能問題通常是由少數(shù)幾個SQL語句所導(dǎo)致的,它們產(chǎn)生了大量IO導(dǎo)致了整個數(shù)據(jù)庫的性能下降。優(yōu)化幾條問題語句往往就能解決整個數(shù)據(jù)庫的IO性能問題。
從Oracle 10g開始,ADDM能夠自動檢測出問題語句,同時,再通過查詢優(yōu)化建議器能夠自動優(yōu)化語句并降低它們對IO的消耗。關(guān)于ADDM和查詢優(yōu)化建議器可以參考文章《Oracle 10G 新特性——ADDM和查詢優(yōu)化建議器》。
在這種方法中,主要有兩種途徑來實現(xiàn)對IO的優(yōu)化。
通過一些內(nèi)存緩存,如Buffer Cache、Log Buffer、Sort Area,可以降低數(shù)據(jù)庫對IO的請求。
當(dāng)Buffer Cache被增大到一定大小時,絕大多數(shù)結(jié)果可以直接從緩存中獲取到,而無需從磁盤上讀取了。而在進行排序操作時,如果Sort Area足夠大,排序過程中產(chǎn)生的臨時數(shù)據(jù)可以直接放在內(nèi)存中,而無需占用臨時表空間了。
控制Multiblock IO的參數(shù)叫DB_FILE_MULTIBLOCK_READ_COUNT,它控制在多數(shù)據(jù)塊讀時一次讀入數(shù)據(jù)塊的次數(shù)。適當(dāng)增加這個參數(shù)大小,能夠提高多數(shù)據(jù)塊操作(如全表掃描)的IO效率。例如,讀取100M數(shù)據(jù),如果每次讀取1M一共讀取100次的效率就比每次讀取100K一共讀取1000次更快。但是這個數(shù)字達到一定大小后,再增加就作用不大了:每次10M一共讀100次來讀取1G的數(shù)據(jù)的效率和單獨一次讀取1G數(shù)據(jù)的效率是沒有多大區(qū)別的。這是因為IO效率受到2個因素的影響:IO建立時間和IO傳輸時間。
IO建立時間對于不同IO大小來說都是相同的,它決定了對小IO的總的IO時間,增大Multiblock IO大小可以減少IO建立時間;
IO傳輸時間與IO大小是成正比的,在小IO時,IO傳輸時間一般比IO建立時間少,但對于大IO操作來說,IO傳輸時間決定了總的IO時間。因此Multiblock IO大小增大到一定大小時,它對總的IO時間影響就不大了。
如我們前面所介紹的,利用一些操作系統(tǒng)提供的提升IO性能的特性,如文件系統(tǒng)的異步IO、Direct IO等來優(yōu)化數(shù)據(jù)庫系統(tǒng)的IO性能。另外一種方法就是增加每次傳輸?shù)淖畲?/span>IO大小的限制(大多數(shù)Unix系統(tǒng)中,由參數(shù)max_io_size控制)。
ASM(Automatic Storage Manager自動存儲管理)是從Oracle 10g開始引入的。它是一個建立在數(shù)據(jù)庫內(nèi)核中的文件系統(tǒng)和卷管理器。它能自動將IO負(fù)載均衡到所有可用的磁盤啟動器上去,一避免“熱區(qū)”。ASM能防止碎片,因此無需重建數(shù)據(jù)來回收空間。數(shù)據(jù)被均衡分布到所有硬盤上。
這個方法通過一些成熟的存儲技術(shù),如條帶化、RAID、SAN和NAS,來將數(shù)據(jù)庫IO分布到多個可用的物理磁盤實現(xiàn)負(fù)載均衡,以避免在還存在空閑可用磁盤時出現(xiàn)的磁盤爭用和IO瓶頸問題。
關(guān)于這幾種存儲技術(shù),我們文章的前面部分都有做介紹。
當(dāng)數(shù)據(jù)庫系統(tǒng)中缺乏以上各種存儲技術(shù)手段時,我們可以考慮使用這種方式。這樣做的目的是使數(shù)據(jù)庫的IO得到均勻分布,從而避免在還有空閑磁盤時出現(xiàn)磁盤爭用和IO瓶頸問題。當(dāng)然這種手工分布IO方法是無法達到以上的自動分布IO的效果的。
系統(tǒng)中總會存在一些IO是無法消除或降低的。如果采用以上手段還不能滿足IO性能要求的話,可以考慮這兩種方法: