数据库性能优化—全局优化思路
一、數據庫訪問優化法則
要正確的優化SQL,我們需要快速定位能性的瓶頸點,也就是說快速找到我們SQL主要的開銷在哪里?
大多數情況性能最慢的設備會是瓶頸點,如下載時網絡速度可能會是瓶頸點,本地復制文件時硬盤可能會是瓶頸點,為什么這些一般的工作我們能快速確認瓶頸點呢,因為我們對這些慢速設備的性能數據有一些基本的認識,如網絡帶寬是2Mbps,硬盤是每分鐘7200轉等等。因此,為了快速找到SQL的性能瓶頸點,我們也需要了解我們計算機系統的硬件基本性能指標,下圖展示的當前主流計算機性能指標數據:
1、從圖上可以看到基本上每種設備都有兩個指標:
- 延時(響應時間):表示硬件的突發處理能力;
- 帶寬(吞吐量):代表硬件持續處理能力。
2、從上圖可以看出,計算機系統硬件性能從高到代依次為:
CPU——Cache(L1-L2-L3)——內存——SSD硬盤——網絡——硬盤
由于SSD硬盤還處于快速發展階段,所以本文的內容不涉及SSD相關應用系統。
3、根據數據庫知識,我們可以列出每種硬件主要的工作內容:
CPU及內存:緩存數據訪問、比較、排序、事務檢測、SQL解析、函數或邏輯運算;
網絡:結果數據傳輸、SQL請求、遠程數據庫訪問(dblink);
硬盤:數據訪問、數據寫入、日志記錄、大數據量排序、大表連接。
4、根據當前計算機硬件的基本性能指標及其在數據庫中主要操作內容,可以整理出如下圖所示的性能基本優化法則:
由于每一層優化法則都是解決其對應硬件的性能問題,所以帶來的性能提升比例也不一樣。傳統數據庫系統設計是也是盡可能對低速設備提供優化方法,因此針對低速設備問題的可優化手段也更多,優化成本也更低。我們任何一個SQL的性能優化都應該按這個規則由上到下來診斷問題并提出解決方案,而不應該首先想到的是增加資源解決問題。
以下是每個優化法則層級對應優化效果及成本經驗參考:
| 優化法則 | 性能提升效果 | 優化成本 | 優化手段 |
| 減少數據訪問 | 1~1000 | 低 | 1、創建并使用正確的索引 2、只通過索引訪問數據 3、優化SQL執行計劃 |
| 返回更少數據 | 1~100 | 低 | 1、數據分頁處理:客戶端分頁、應用程序分頁、sql分頁 2、只返回需要的字段 |
| 減少請求次數 | 1~20 | 低 | 1、批提交batch DML 2、In List:一個ID一個請求發給數據庫改成In List的寫法 3、設置Fetch Size 4、使用存儲過程 5、優化業務邏輯 6、使用ResultSet游標處理記錄 |
| 減少服務器CPU開銷 | 1~5 | 低 | 1、使用綁定變量 2、合理使用排序 3、減少比較操作 4、大量復雜運算在客戶端處理 |
| 利用更多資源 | @~10 | 高 | 1、客戶端多進程并行訪問 2、數據庫并行處理 |
二、數據庫優化手段詳解
1、減少數據訪問
1)創建并使用正確的索引
如果我們把一個表的內容認為是一本字典,那索引就相當于字典的目錄,如下圖所示:
一般在什么字段上建索引?這是一個非常復雜的話題,需要對業務及數據充分分析后再能得出結果。主鍵及外鍵通常都要有索引,其它需要建索引的字段應滿足以下條件:
1)字段出現在查詢條件中,并且查詢條件可以使用索引;
2)語句執行頻率高,一天會有幾千次以上;
3)通過字段條件可篩選的記錄集很小,那數據篩選比例是多少才適合?
這個沒有固定值,需要根據表數據量來評估,以下是經驗公式,可用于快速評估:
小表(記錄數小于10000行的表):篩選比例<10%;
大表:(篩選返回記錄數)<(表總記錄數*單條記錄長度)/10000/16,單條記錄長度≈字段平均內容長度之和+字段數*2
2)只通過索引訪問數據
有些時候,只訪問表中的幾個字段,并且字段內容較少,我們可以為這幾個字段單獨建立一個組合索引,這樣就可以直接只通過訪問索引就能得到數據,一般索引占用的磁盤空間比表小很多,所以這種方式可以大大減少磁盤IO開銷。
如:select id,name from company where type='2';,如果這個SQL經常使用,我們可以在type,id,name上創建組合索引
create index my_comb_index on company(type,id,name);
有了這個組合索引后,SQL就可以直接通過my_comb_index索引返回數據,不需要訪問company表。
還是拿字典舉例:有一個需求,需要查詢一本漢語字典中所有漢字的個數,如果我們的字典沒有目錄索引,那我們只能從字典內容里一個一個字計數,最后返回結果。如果我們有一個拼音目錄,那就可以只訪問拼音目錄的漢字進行計數。如果一本字典有1000頁,拼音目錄有20頁,那我們的數據訪問成本相當于全表訪問的50分之一。
切記,性能優化是無止境的,當性能可以滿足需求時即可,不要過度優化。在實際數據庫中我們不可能把每個SQL請求的字段都建在索引里,所以這種只通過索引訪問數據的方法一般只用于核心應用,也就是那種對核心表訪問量最高且查詢字段數據量很少的查詢。
3)優化SQL執行計劃
?
2、返回更少的數據
1)數據分頁處理
| 客戶端(應用程序或瀏覽器)分頁 | 數據:應用服務器 -> (本地應用程序或瀏覽器),在應用程序或瀏覽器內部通過本地代碼進行分頁處理。 | 編碼簡單,減少客戶端與應用服務器網絡交互次數 | 首次交互時間長,占用客戶端內存 | 客戶端與應用服務器網絡延時較大,但要求后續操作流暢,如手機GPRS,超遠程訪問(跨國)等等。 |
| 應用服務器分頁 | 數據:數據庫服務器 -> 應用服務器,在應用服務器內部再進行數據篩選。 以下是一個應用服務器端Java程序分頁的示例: List list=executeQuery(“select * from employee order by id”);Int count= list.size();List subList= list.subList(10, 20);? | 編碼簡單,只需要一次SQL交互,總數據與分頁數據差不多時性能較好。 | 總數據量較多時性能較差。 | 數據庫系統不支持分頁處理,數據量較小并且可控。 |
| 數據庫SQL分頁 | 采用數據庫SQL分頁需要兩次SQL完成:一個SQL計算總數量,一個SQL返回分頁后的數據 | 性能好 | 編碼復雜,各種數據庫語法不同,需要兩次SQL交互。 | ? |
2)只返回需要的字段
通過去除不必要的返回字段可以提高性能,例:
調整前:select * from product where company_id=?;調整后:select id,name from product where company_id=?;優點:
1、減少數據在網絡上傳輸開銷
2、減少服務器數據處理開銷
3、減少客戶端內存占用
4、字段變更時提前發現問題,減少程序BUG
5、如果訪問的所有字段剛好在一個索引里面,則可以使用純索引訪問提高性能。
缺點:增加編碼工作量
由于會增加一些編碼工作量,所以一般需求通過開發規范來要求程序員這么做,否則等項目上線后再整改工作量更大。
如果你的查詢表中有大字段或內容較多的字段,如備注信息、文件內容等等,那在查詢表時一定要注意這方面的問題,否則可能會帶來嚴重的性能問題。如果表經常要查詢并且請求大內容字段的概率很低,我們可以采用分表處理,將一個大表分拆成兩個一對一的關系表,將不常用的大內容字段放在一張單獨的表中。如一張存儲上傳文件的表:
T_FILE(ID,FILE_NAME,FILE_SIZE,FILE_TYPE,FILE_CONTENT)我們可以分拆成兩張一對一的關系表:
T_FILE(ID,FILE_NAME,FILE_SIZE,FILE_TYPE)T_FILECONTENT(ID, FILE_CONTENT)?????????通過這種分拆,可以大大提少T_FILE表的單條記錄及總大小,這樣在查詢T_FILE時性能會更好,當需要查詢FILE_CONTENT字段內容時再訪問T_FILECONTENT表。
轉自:http://my.oschina.net/xianggao/blog/87216
另有參考?http://my.oschina.net/xianggao/blog/87448?數據庫性能優化之SQL語句優化2
http://my.oschina.net/xianggao/blog/87450?數據庫性能優化之SQL語句優化3
http://my.oschina.net/xianggao/blog/87453?數據庫性能優化之SQL語句優化4
http://my.oschina.net/xianggao/blog/87223??關于如何形成一個好的數據庫設計
總結
以上是生活随笔為你收集整理的数据库性能优化—全局优化思路的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 消息队列—主要消息中间件优势对比
- 下一篇: mysql索引实现原理