數據庫查詢性能優化一直是程序員繞不開的話題,當咱們遇到業務刷新報表緩慢或者查詢獲取結果延遲太大,能夠採用提問法來思考如何進行優化。
ios
1. 什麼樣的環境
硬件環境
query執行的速度和咱們的硬件息息相關,當前用的什麼樣的CPU,有多少核多少線程, 內存有多大都直接影響了運算速度, 磁盤是SSD仍是HDD,網卡什麼速率都直接影響了咱們數據讀取的時延程序員
軟件環境
軟件環境雖然不像硬件同樣,各類參數看的見摸得着,但仍然影響着咱們的查詢性能。沒一套系統實際上都在特定的場景有着各自的優點。咱們的查詢系統是什麼樣的架構,適合什麼樣的query,在線仍是離線, 計算多仍是數據讀取多,這些在咱們作優化的時候都應該瞭然於心。web
下面咱們根據這種思路來看看如何作性能優化數據庫
2. 什麼樣的query
首先咱們優化查詢的時候,須要看看query 到底是哪一種類型。寫入仍是查詢(這裏鑑於篇幅只談查詢), CPU密集仍是IO密集。若是咱們的系統是適合OLTP低延時點查的場景, 想要在這種系統上作OLAP大規模分析很顯然就不太適合, OLTP通常專一於數據一致性較高的點查,而OLAP因爲數據量龐大,通常都須要採用向量併發查詢。OLAP不專一於毫秒級的低延遲, 而OLTP不專一於上億級的數據統計。性能優化
3. 如何尋找性能瓶頸
3.1 vmstat查看系統狀況
總體系統不知道當前的瓶頸在哪裏時, 咱們能夠先用vmstat工具來簡單的看一下系統的大體狀況。以下圖所示,2表示每一個兩秒採集一次服務器狀態。服務器
procs : 查看進程狀態
r : 運行隊列,即當前可運行(正在運行或者等待運行)的進程數量。目前CPU比較空閒,這個數量很小,當這個值超過了CPU數目,就會出現CPU瓶頸了。微信
b : 阻塞的進程,即處在不可中斷sleep狀態下的進程數量。網絡
memory : 查看內存狀態
swpd : 已使用的虛擬內存大小,若是大於0,表示機器開始使用虛擬內存了,虛擬內存運行會很慢。這裏數值爲0表示咱們關閉了虛擬內存功能。session
free : 空閒的物理內存的大小。數據結構
buff : 內存作爲系統buffers的大小。
cache : 內存作爲系統cache的大小。
swap : 磁盤和內存作數據交換的狀態
nesi : 每秒從磁盤讀入虛擬內存的大小,若是這個值大於0,表示物理內存不夠。
so : 每秒虛擬內存寫入磁盤的大小。
io:磁盤的io信息
bi : 每秒從塊設備接收的塊數量。
bo : 每秒發送給塊設備的塊數量。
若是這兩個值較大,表示IO比較頻繁,能夠考慮IO優化。
system : 系統狀態信息
in : 每秒CPU的中斷次數(包括時鐘中斷)
cs : 每秒上下文切換次數,咱們調用系統函數、線程的切換,就須要上下文切換,這個值要太大就能夠考慮 減小系統的上下文切換,好比協程替代多線程等方式。
CPU : CPU信息
us : 包括用戶時間和nice時間,跑非內核的代碼(或者用戶代碼)的時間。
sy : 系統佔用時間,跑內核代碼(好比系統調用)佔用的時間。
id : 花費在idle上的 CPU時間。
wa : 等待IO CPU時間。若是這個值太大,表示IO系統瓶頸在IO上。
若是CPU佔用高表示系統在CPU上, 若是系統的swap比較頻繁,極可能是系統內存泄露或者內存不夠用,須要擴展內存, 若是是IO等待較多則系統瓶頸出如今IO上,若是上下文切換,或者系統調用佔比太大,則咱們須要思考下咱們程序的設計,減小系統調用或者上下文切換。
3.2 CPU佔用太高
咱們能夠經過uptime、top、mpstat或者sar等一些工具來查看當前CPU佔用太高的狀況.
咱們能夠經過uptime看看當前系統的總體狀況, 當前的系統時間和運行時間, 登錄的用戶數量,還有最近五、10和15分鐘的系統平均負載。
top則能夠顯示較詳細的信息。head部分有CPU佔用的詳細信息, 下面的列表也有記錄每一個進程佔用的CPU狀況。
若是是多線程, 咱們還能夠經過top -H -p pid來查看進程的每一個線程的CPU佔用狀況
咱們找到哪一個線程佔用的比例多以後, 能夠根據這個線程的線程名查看該線程是用來作什麼處理的。大體瞭解下是什麼樣的處理讓CPU比較高。
mpstat則能夠查看系統每一個核的運行狀態。
sar的功能比較全,這裏再也不作科普。
CPU用戶態的佔用比較高,通常就是咱們的程序編寫的效率過低,具體哪裏低,咱們能夠經過perf工具或者Intel的vtunes來查看性能瓶頸。perf top的執行結果以下圖所示, 咱們拿到對應的堆棧信息以後, 就能夠針對性的消除CPU瓶頸了。(vtune的用法能夠自行谷歌)。
鑑於上述工具檢查出來的狀況, 若是CPU確實水位很高,則CPU基本就是性能瓶頸。若是不高則,須要進行下一步來判斷性能瓶頸。
3.3 IO佔用太高的狀況
IO定位的工具多種多樣, 通常查看IO問題咱們可使用iostat、pidstat和iotop工具。固然咱們也可使用其餘的工具,你們能夠本身搜索相關的工具使用, 這裏主要介紹經常使用的幾種工具。
pidstat
pidstat是sysstat工具的一個命令,用於監控所有或指定進程的cpu、內存、線程、設備IO等系統資源的佔用狀況。用戶能夠經過指定統計的次數和時間來得到所需的統計信息。
咱們經過這個命令能夠知道哪一個進程佔用的IO比較多。而後咱們能夠經過指定進程號的方式查看更詳細的信息。
這樣咱們就能夠知道是哪一個進程中的哪一個線程佔用了較多的IO資源,而後咱們能夠經過對應的TID,找到對應的執行代碼進行分析。
iostat
iostat是I/O statistics(輸入/輸出統計)的縮寫,它能夠對系統的磁盤操做活動進行監控,彙報磁盤活動統計狀況。可是iostat僅對系統的總體狀況進行統計,不能對某個進程進行深刻分析,單獨的進程分析咱們能夠用iotop工具,使用方法和top相似。
1 表示每秒打印一次當前磁盤的統計信息。咱們須要注意的是後面幾個指標。
avgrq-sz | 平均每次IO操做的數據量(扇區數爲單位) |
---|---|
avgqu-sz | 平均等待處理的IO請求隊列長度 |
await | 平均每次IO請求等待時間(包括等待時間和處理時間,毫秒爲單位) |
svctm | 平均每次IO請求的處理時間(毫秒爲單位) |
%util | 採用週期內用於IO操做的時間比率,即IO隊列非空的時間比率 |
左右滑動查看完整表格
avgrq-sz直接反應了當前io的種類,好比大塊數據讀取仍是小數據量的讀取。
avgqu-sz反應了當前IO的繁忙狀況, 若是隊列長度太長,說明IO如今很忙不少任務處理不過來,換句話說 I,IO成爲了瓶頸。
await 也是同樣, 若是等待比較高,說明IO成了累贅。
svctm則和avgrq-sz同樣,反應了IO操做的處理規模,若是是大塊數據讀寫, 這個時間就會拉長。
iotop
iotop 能夠用於查看哪些進程執行佔用了的 I/O,使用方式和top相似,這裏再也不作過多描述。
3.4 其餘狀況
若是TOP佔用不高, IO也不是瓶頸,則可能處在程序架構上, 好比並發控制的不夠好有較多的線程在sleep狀態。這種狀況能夠經過pstack看看當前全部線程的堆棧。
4. 優化性能瓶頸
CPU瓶頸型
面對這種類型,通常咱們須要經過perf配合對應的代碼去進行優化,核心思想就是減小計算的量。具體方法如下僅供參考:
多采用SIMD來代替老式的計算指令或者C++的操做運算符。能夠引進相似Intel的MKL庫來輔助計算。
減小沒必要要的重複計算,減小for循環的次數。好比有些std庫的數據結構都有find函數都帶有起始座標,善用起始座標避免從0座標重複查詢。
若是是系統調用過多,好比分配內存之類的,能夠考慮預分配內存的方式,或者直接使用tcmalloc等相似的內存管理庫進行兜底,有條件的能夠基於這類庫再開發適合本身的內存管理體系
IO瓶頸型
IO瓶頸通常都是和磁盤相關的,網絡上,由於網卡升級,速度上去比較快,相比來講,限制的io基本都是磁盤上的io.下面也只說說磁盤的IO優化方法。
若是是讀類型的請求形成了IO瓶頸, 能夠考慮上層多開cache。好比全局的query cache, session級別的session cache, 塊設備的block cache等,從上層去減小磁盤的io請求。
若是是是小數據大併發的寫入類型的形成了IO瓶頸,咱們能夠考慮在內存作一次cache,對這屢次寫入先在內存處理,而後經過時間或者大小閾值等策略控制,刷到磁盤上。
若是是大數據的寫入,咱們能夠考慮作下平滑寫入,每次限制寫入的數量。
若是是由於流量的關係,某一時間點出現峯值,以後回落,則能夠考慮經過第三方來寫入。好比消息隊列,先寫到消息隊列i進行削峯,再平滑寫入系統。
除此以外咱們還能夠換更好的硬件,好比磁盤陣列等。
內存瓶頸型
內存瓶頸通常比較難出現,內存畢竟比較便宜,基本上都會知足內存的需求。若是真的由於虛擬內存的問題形成了程序運行效率低下,咱們一方面是考慮增長內存,關閉虛擬內存來解決,同時咱們也應該思考本身的程序模型,好比減小中間數據的存在, 多用寫時複製技術,多用用系統的no copy接口替換老的接口等。
5. 後續
若是實在沒有方法優化了,咱們真的就須要看看當前的query是否真的合適咱們的系統了。仍是那句話,每套系統都有適合本身的業務,通常公司的系統體系裏都會有多種數據庫引擎,針對咱們的query,去尋找合適的引擎也是一種方法。
☆ END ☆
OPPO互聯網技術團隊招聘一大波崗位,涵蓋C++、Go、OpenJDK、Java、DevOps、Android、ElasticSearch等多個方向,請點擊這裏查看詳細信息及JD。
更多技術乾貨
掃碼關注
OPPO互聯網技術
本文分享自微信公衆號 - OPPO互聯網技術(OPPO_tech)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。