有關數據庫的優化這個問題
平常一般我們接觸的比較少
所以有時沒有引起足夠的重視
但是在某些時候
這將關系到整個軟件的成敗
一般來說
我們考慮要做數據庫的優化的時候
是建立在設計已經定型的基礎上的
往往設計此時已經很難更改或者根本無法更改
所以對於太糟糕的設計
我們往往是無能為力的
比如需要提取的某個信息的時候
需要輾轉多個大表
且返回記錄數較多
那麼這種情況在設計的時候我們希望能予以盡可能的關注
數據庫的設計應該和實際業務(功能)結合起來選擇一個設計的平衡點
不能一味的追求范式級別是怎麼的高
有時甚至需要通過一些數據冗余來提高查詢效率
那麼在所有這些成為事實
我們已經進入編程階段的時期之後
對於我們具體的數據庫編程人員來講
要考慮的就是以下幾類問題
一
網絡流量
二
磁盤I/O
三
資源的使用
四
代碼效率
網絡流量 通常我們在兩種情況下要考慮這個問題
. 繁發送的SQL請求 比如web數據庫的訪問
這種情況下sql語句的傳送都有可能給網絡造成沉重的負擔
可以考慮采用存儲過程或者函數的方式來緩解問題
一般來說
這種情況下應用服務器應該提供pool和數據庫建立常連接供調用
因為對數據庫的連接請求和數據庫的響應是一個比較耗時的過程
這往往成為數據庫瓶頸
.一次性返回記錄過多 使用者未必需要看所有記錄
或者他一次可以看一部分記錄
這時就可以通過前台采用翻頁等措施
來緩解網絡的壓力
而後台則可以通過多種方式來實現
比如游標
比如利用中間結果集一次性返回的方式等
總之
對於網絡流量的考慮
也是一個根據具體需求和環境衡量的結果
如果沒有必要讓我們來考慮這個問題
那麼
你就大膽的做吧
在LAN中一次返回
k的數據大家都還可以接受
順便提一下
有時可能要網絡傳送的包的大小問題
因為包總有一些固定大小的標記
所以包太小則對於業務無用的信息太多
包太大而又可能造成經常發送失敗
磁盤I/O一般來說這個問題跟數據庫管理員或者設計人員的關系更密切
但我們需要做的是
盡可能的利用索引
對於太大的表
利用表數據分區存儲的特點(當然這需要你首先明白什麼是表分區和它可以帶來什麼好處)
利用索引能提高速度是因為兩個原因
一是索引通常比數據占用的空間小
每次從磁盤讀入內存的時候更快
二是索引的存儲結構是一種平衡的樹的形式
它不是順序的查找的
根據樹的特點
我們可以估算出其查找次數大致應該為n=logn(x)
x為記錄數
若不利用索引則許查找x次(當然這好象跟磁盤I/O已經沒有關系了)
再提醒一點
若記錄返回數大於
%
則數據庫將可能做全表掃描
此時索引反而降低了數據庫的效率
資源的使用其實我們最關心的資源
除了網絡
就是內存和cpu
要在這方面作出優化
必須明白數據庫的體系結構和數據庫對於sql到底是怎麼解析執行的
對於發送的sql語句
數據庫先解析若發現有完全和該語句相同的已經解析好的執行代碼存在於緩沖區中
則直接執行緩沖區中代碼
要利用這點
要求我們編寫代碼具有良好的風格和習慣
所謂完全相同的sql語句的意思是該語句所有字符甚至空格和換行都完全一樣
想想存儲過程的快主要就是因為它是解析好的代碼存儲在數據庫中而可以直接調用
關於cpu的利用的明顯的地方就是多處理器的情況下
應該在查詢中指定並行查詢
利用多個cpu並行的能力
關於內存的使用
這是數據庫管理員和我們編程人員應該共同關心的問題
因為數據庫緩沖區是為了保存已經執行或者使用過的數據留下的信息以為下次執行使用
這樣既降低了磁盤I/O
也減少了一些重復的執行步驟
首先要明白數據庫緩沖區采用的是先淘汰最近使用最少的數據的策略
當然
其中還有優先級別等問題
對於通過索引讀入的數據和索引本身
在數據庫中保留的時間總是比較長
若這樣的數據充斥了緩沖區
那帶來的結果是我們不願意看到的
還有一點
若臨時表或者中間結果過大
也會有類似的影響
這些在編程的時候可能會遇到
代碼效率大多數情況下
這才是編程人員關心的重點
要使代碼效率高
我們當然希望它占用的內存小
耗用的時間短
但某些情況下
這
點可能成為一對矛盾
比如
我們要提取符合條件的從
條到
條的記錄
我們決定采用游標的方式
那麼一種可能
我們打開一個游標
然後順序移動到第
條記錄處
開始提取數據
結束後關閉游標
一種可能
我們采用中間結果集或者臨時表等方式
先找出符合條件的記錄中的
條到
條
然後在這個基礎上定義游標
那麼這樣我們的游標就避免了
次的移動
但是代價是這個過程中利用了更多的內存
不過
我們編程
本就沒有一個完美的解決方案
總是根據具體情況做出一個比較合適的選擇的
其實
更多的
我們應該關心SQL語句在數據庫中到底是怎麼解析並執行的
從這個層次
上明白了
寫出的sql語句就至少不會太差了
當然
一開始
我們可以記住一些通用規則
比如查詢中盡可能的利用索引
能過濾掉最多數據的條件寫在where子句的末尾
在使用子查詢的時候要慎重考慮
對於in要仔細衡量
not in要盡量避免使用
表連接的時候要盡量利用索引字段
多表連接的時候要注意連接順序
還有比如like的使用
不要輕易使用like%s%這樣的條件(like s%是可以利用索引的)
這種匹配的算法再快也有影響
多了解sql編碼中的一些技巧
多積累經驗
多學習
在已經知道的東西中根據需要靈活的創造出自己的用法
這時你心裡就應該清楚自己的代碼的執行效率了
不至於N個月後運行的時候突然發現需要返工
那將是一件很痛苦的事情
最後再強調一點
要做到對自己編寫的代碼心中有數
很明白它有多大的承受能力
你
就必須理解數據庫的體系結構
明白SQL代碼的執行過程
知道這個執行過程中大約要消耗多少內存
有那些更詳細的步驟
它會給數據庫帶來什麼樣的影響
這個影響可以忽略麼?只要咱們朝著這個方向努力
最終會玩轉這個內容並不太多的東東的
(<b>biti_rainy</b>)
對於的看法 包
存儲過程函數等是針對計算密集型和後台數據處理密集型的業務邏輯
而一點從 App Server 層傳的 sql 就能造成網絡沉重負擔?提交的表單數據都比 SQL 字節多!而對於連接
一般都用 connection pool
即使用 tomcat 也自己寫 pool 了
況且連接請求和SQL請求完全是兩碼事嘛
對於的看法 分頁是理所當然的
可是沒有必要用什麼游標吧?(我想你指的是服務端游標吧
其實客戶端結果集本身就打開了客戶端游標)
難道為一個分頁就寫一個存儲過程?利用兩次 rownum 結合就搞定了
其實網絡流量的問題
只要程序中不出現返回幾千
萬行記錄的
地雷
程序就沒問題
除非你用
M或
M網卡
服務器都應該用
M 以上的網絡設備了
對於磁盤 I/O 最有效的辦法是對數據庫分區
對表分區
對索引分區
以及結合二者
然後對 SQL 進行優化
使之利用分區
SQL優化比較煩人
需要花一些時間
而且還要用到 hint
Oracle 有一個文檔
什麼 performance 什麼裡面講很清楚
如何寫 SQL 都很有學問
讀清楚那本書就 ok 了如果分區和SQL優化做得好
CPU利用率不會太高
相對而言數據庫服務器吃內存比較狠
應用服務器用 CPU 比內存重要些
(<b>singledream</b>)
From:http://tw.wingwit.com/Article/program/Oracle/201311/17020.html