程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> Oracle數據庫 >> Oracle數據庫基礎 >> Oracle數據庫性能模型

Oracle數據庫性能模型

編輯:Oracle數據庫基礎

最近一直在思考一個問題:如何為一個數據庫建立性能模型?作為一名DBA來說,我們面臨的一個巨大挑戰是:如何保證數據庫的性能可以滿足快速變化的應用的需求,如何在數據量和訪問量持續增長的情況下,保證應用的響應時間和數據庫的負載處在合理的水平下。我們可能會經常面對以下的問題:某個SQL每秒要執行100次,響應時間是多少?某個應用發布後,對數據庫的影響如何?所以,評估應用對數據庫所產生的影響,優化應用並預測風險,保證數據庫的可用性和穩定性,這是應用DBA真正有價值的地方。

響應時間為中心:

如果要選擇一個評價系統優劣的性能指標,毫無疑問應該是響應時間。響應時間是客戶體驗的第一要素,所有的優化都應該為降低響應時間而努力。對於數據庫系統也是如此,我們優化系統,優化SQL,最終目標都是為了降低響應時間,單位時間內可以處理更多的請求。

數據庫時間模型:

響應時間一般分為服務時間(Service time)和等待時間(Wait time),服務時間指進程占用CPU的時間,包括前台進程(Server process)和後台進程(Backgroud process),我們一般只關注前台進程占用的CPU time。等待時間包括很多類型,一般最常見的是IO等待和並發等待,IO等待包括sequential read,scattered read和log file sync等等,而並發等待主要是latch和enqueue。SQL execute elapsed time指用戶進程執行SQL的響應時間,包含CPU time和wait time。

以下是Oracle數據庫的時間模型:

在Oracle系統中,我們可以利用AWR或Statspack報告,看到數據庫的時間信息:

Statistic Name Time (s) % of DB Time sql execute elapsed time 3,062.17 91.52 DB CPU 2,842.08 84.95 parse time elapsed 25.87 0.77 PL/SQL execution elapsed time 11.75 0.35 sequence load elapsed time 7.55 0.23 hard parse elapsed time 5.06 0.15 connection management call elapsed time 3.13 0.09 hard parse (sharing criteria) elapsed time 0.04 0.00 repeated bind elapsed time 0.01 0.00 PL/SQL compilation elapsed time 0.00 0.00 DB time 3,345.74   background elapsed time 204.91   background cpu time 72.30  

DB time是整個數據庫用戶進程消耗的總時間,是從第一項到第十項時間的總和(從sql execute elapsed time到PL/SQL compilation elapsed time),但是我們會發現這十項時間的總和比DB Time要大一些,這是因為部分時間信息有重疊的部分,比如SQL execute elapsed time就包括了很大一部分DB cpu的時間。而background elapsed time和background cpu time則是Oracle後台進程消耗的時間和cpu time。

數據庫響應時間分析:

數據庫系統的響應時間由四個要素決定:CPU,IO,內存和網絡其中CPU和IO是最重要的因素。與之相比,內存與網絡則簡單很多,因為通常情況下,對於一個調優的系統來說,內存訪問的延遲時間非常小(100 ns以下,1 ms=1000000 ns)相比較CPU和IO幾乎可以忽略。而網絡延遲則通常是一個常數,比如在一個數據中心的情況下,網絡的延遲一般在3ms以下,如果存在多數據中心的情況,網絡延遲可能會超過20ms,所以對於一個分布式系統來說,網絡延遲是必須要考慮的問題。

在這裡,我們不考慮分布式系統,並且忽略內存的訪問延遲,重點分析CPU和IO,我們看以下數據庫的AWR片段:

AWR片段

我們看到這個系統中DB CPU占整個DB time的87.21%,User I/O占整個DB time的9.12%,commit相關的IO等待占2.35%(主要是log file sync),CPU和IO占用了整個DB time的96.68%。由於DB CPU所占的比例很高,所以這個數據庫系統是CPU intensive類型,這裡的DB CPU主要是執行SQL的服務時間。

我們再看另外的一個數據庫的AWR片段:

另一個AWR片段

我們看到,Commit和User I/O占DB time的81.46%,而DB CPU只占13.82%,所以這個數據庫系統是IO instensive類型的。

Physical read

Physical read是指Oracle在buffer cache中沒有找到相應的block,需要從IO子系統讀取相應的block的過程,對應的IO稱為物理IO,物理讀數量代表物理IO讀取的block數量。因為一般IO子系統都是慢速的磁盤,所以物理IO對整體響應時間的影響非常大,如果發生大量的物理IO,整個系統的響應時間會變得很差。系統的IO子系統可能是文件系統,裸設備或者ASM,底層硬件可能是SAN存儲,NAS存儲或者普通SAS磁盤等等。為了提高響應時間,通常在物理磁盤與Oracle之間增加cache層,對於Oracle來說,物理IO並不一定是真正訪問磁盤,很可能是訪問文件系統cache,存儲的cache等等。

不管IO subsystem是什麼,Oracle只關心物理IO的響應時間。通過AWR報告,我們可以看到物理IO的響應時間:

I/O響應時間

db file sequential read(單塊讀,隨機IO)的平均響應時間為3ms,db file scattered read(多塊讀,連續IO)的平均響應時間是4ms,logfile file sync的平均響應時間是3ms,前兩者的Wait class是User I/O,代表用戶進程讀操作的響應時間,logfile sync的wait class是Commit,代表lgwr進程寫redo的響應時間,因為用戶commit必須完成log file sync的操作,所以它也會直接影響用戶進程寫操作的響應時間。

關於物理IO的響應時間,我們有一個經驗值。對於Sequential read和Scattered read,我們認為小於10ms屬於正常狀態,而大於10ms則認為IO subsystem的響應延遲過大。所以我們在衡量存儲系統的性能時,只有響應時間在10ms以下的IO我們認為是有效的。這裡有一個有趣的現象,就是sequential read和scattered read的響應時間幾乎相差無幾,也就是說隨機IO讀取8K數據和連續IO讀取128K數據,響應時間差別很小,這是由磁盤的機械特性造成的,延遲時間=尋道時間+

對於log file sync的響應時間,因為用戶commit必須完成log file sync,所以整個系統的寫操作的響應時間都取決於它的響應時間,而且從整個數據庫系統的角度去看,log file sync幾乎是串行的,所以這個響應時間對寫操作影響非常大,我們的經驗值是必須保證在5ms以下,如果超過5ms整個系統的寫操作都會受到嚴重的影響。

Logical read

Logical read是Oracle從buffer cache中讀取block的過程,對應的IO稱為邏輯IO,邏輯讀數量代表邏輯IO讀取的block數量因為Oracle必須首先將block讀入buffer cache中(direct path read除外),所以邏輯讀數量包含了物理讀數量。對於一個SQL來說,邏輯讀數量是衡量其性能的標准,而不是物理讀。雖然物理IO的響應延遲比邏輯IO大很多,但是物理讀數量會隨著執行次數而變化(頻繁讀取導致block被緩存在buffer cache中)。對於一個系統也是如此,邏輯讀應該是數據庫性能評估模型的核心我們需要建立邏輯讀與響應時間的對應關系。

每個邏輯讀的響應時間是多少,這是一個巨大的挑戰。因為每個邏輯讀背後隱藏了很多動作,可能包括物理讀,等待事件,CPU time等等。我對很多數據庫的AWR報告做了分析,期望根據經驗值建立一個簡化的模型。我們假設一個數據庫如果是充分調優的,除CPU time和IO以外的等待時間應該盡可能少(應小於DB time 10%)。在這個前提下,我們只關心CPU time和IO的影響,並將系統分為三類:CPU密集型,IO密集型和混合型:

1.IO密集型

User IO     85%
DB CPU        5%
每邏輯讀響應時間0.1-0.5ms

2.CPU密集型

DB CPU         85%
User IO        10%
每邏輯讀響應時間小於0.01ms

3.混合型

User I/O     60%
DB CPU         20%
每邏輯讀響應時間0.05-0.1ms

以上數據是根據很多個典型數據庫的AWR報告計算出來的經驗值,計算公式很簡單:DB time/邏輯讀=每邏輯讀響應時間。因為並沒有考慮硬件和OS上的差異,所以這個數值並不是特別准確,但我們還是可以發現一些規律:隨著IO所占比例從10%增加到85%,響應時間也從小於0.01ms到0.5ms。

預測系統瓶頸

對於數據庫來說,IO子系統對性能影響非常大,必須保證在一定的IO的壓力下,響應延遲控制在合理的范圍內(前面說的10ms和5ms)。因為每塊磁盤可以承受的IOPS是基本確定的,比如15K的SAS磁盤,在響應延遲不超過10ms的前提下,可以提供150個IOPS,如果不考慮cache的影響,整個存儲子系統的IOPS是比較容易計算的。我們可以在系統上線前,進行大量充分的測試,建立存儲IOPS與響應延遲的模型,這樣我們就可以預測出性能出現拐點的風險,提前做出擴容的判斷。在AWR報告中,我們可以得到每秒的物理IO的數量和響應時間,可以方便的實現性能監控和趨勢預警。

評估CPU的容量瓶頸相對簡單,Oracle中CPU time的計算是每個CPU耗費時間的總和,如果有16顆(核)CPU,1個小時理論上可以提供3600×16=57600s CPU time,不超過57600s CPU time我們可以認為不會在CPU上排隊,系統不會出現CPU瓶頸。但是需要注意的是,除了用戶進程使用CPU以外,操作系統也需要占用CPU資源,用來管理內存和進程調度等。我們在OS上看到的CPU使用率中的sys部分就是系統占用的CPU資源,所以應該考慮至少保留10-20%的CPU資源給OS使用。

並發訪問對數據庫的影響

Oracle是一個Disk-based database,設計的出發點就是大部分數據在外部存儲中,而只有小部分數據被cache在buffer中,它既不同於Memcache這類KV cache,也不同於timesten這類In-memory database。所以,就算是所有的數據都可以被cache在buffer中,在高並發訪問的情況下,也可能會出現大量的latch等待,最常見的情況就是cache buffer chain。當大量並發訪問同一塊數據時,就很可能會出現cache buffer chain的latch爭用,也就是我們常說的“熱點”。

需要注意的是:Oracle中的latch等待分為spin和sleep兩個部分,spin消耗cpu time,而sleep則是等待時間。所以大量的latch等待不僅僅會產生大量的等待時間,而且會消耗大量的CPU time。

Oracle是一個為並發操作而設計的數據庫,大量的並發讀寫請求,可能會帶來額外的性能消耗。比如讀取一部分頻繁修改的數據,Oracle為了保證一致性讀的需要,會利用undo信息構造產生大量CR block,同時會產生大量的邏輯讀,這樣會消耗額外的CPU和響應時間。

存儲也可能存在熱點的問題,需要前期對存儲系統充分的優化,常見的手段是利用RAID技術,將數據分散在不同的磁盤上,防止出現“熱點”盤。Oracle ASM提供了Rebalance的功能,允許DBA將存儲中的的數據重新分布,達到消除熱點的目的。

總之,Oracle是一個可以提供大量並發讀寫訪問的數據庫系統,但是在很多地方,Oracle又不得采用一些串行的控制手段,比如latch,enqueue和mutex,我們要做的就是盡量降低這些串行控制對數據庫整體性能的影響。

數據庫優化原則

基於響應時間的Oracle優化原則:盡量減少等待時間(Wait time),提高服務時間(Service time)。這也是基於Oracle等待事件的分析方法的基本原則:盡量消除各種等待事件對系統的影響,從而提高系統性能和響應時間。

如果數據庫系統除了CPU和IO以外的等待時間超過DB time的5%以上的話,可能存在某些性能問題,需要DBA采用等待事件的分析方法,對系統或應用進行優化。

–EOF–

後記:為什麼要寫這麼一個主題,因為最近和一位同事探討機器自動審核SQL的問題,就想建立一個簡單的模型,用來開發一個SQL審核工具,開發人員通過工具和預先建立好的模型,就可以確定這個SQL是否存在性能風險。之前我們在做SQL優化的時候,只是關注這個SQL本身是否優化,邏輯讀是多少。但是,很少有人把邏輯讀和響應時間之間的關系建立起來,我試圖想回答這個問題。

關於容量規劃和風險預測其實是一個很有意義的命題,但是我們很多時候都局限在一些具體的技術細節中,而忽略了對整個系統容量的把握,事實上,這也是非常難的一件事。也許到目前為止,我根本沒有達到建立“模型”的程度,但是我試圖將這些方方面面的因素聯系起來,提供一些有用的經驗值給大家,我覺得這個挺有意義。

在這篇文章中,我提到了幾個有意義的經驗值,這是我根據很多數據庫AWR中的信息計算出來的,雖然不保證完全准確,但是我覺得基本是靠譜的。建議每個DBA都應該從AWR中找到這些信息,並判斷自己的數據庫屬於哪種類型,瓶頸在哪裡,是否存在性能風險。當面對諸如“硬件是否能夠滿足性能需求”,“系統明年是否需要擴容”,“應用是否會對系統產生影響”此類問題時,我們可以用這些經驗值給出一個判斷。

關於這個命題,目前只是一個階段性的結果,我還會繼續思考。如果大家有興趣,歡迎和我一起探討這個話題。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved