熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

關於數據庫編碼優化的一些看法的討論

2013-11-13 15:37:21  來源: Oracle 

  有關數據庫的優化這個問題平常一般我們接觸的比較少所以有時沒有引起足夠的重視但是在某些時候這將關系到整個軟件的成敗
  
  一般來說我們考慮要做數據庫的優化的時候是建立在設計已經定型的基礎上的往往設計此時已經很難更改或者根本無法更改所以對於太糟糕的設計我們往往是無能為力的比如需要提取的某個信息的時候需要輾轉多個大表且返回記錄數較多那麼這種情況在設計的時候我們希望能予以盡可能的關注數據庫的設計應該和實際業務(功能)結合起來選擇一個設計的平衡點不能一味的追求范式級別是怎麼的高有時甚至需要通過一些數據冗余來提高查詢效率那麼在所有這些成為事實我們已經進入編程階段的時期之後對於我們具體的數據庫編程人員來講要考慮的就是以下幾類問題
  一網絡流量
  二磁盤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優化比較煩人需要花一些時間而且還要用到 hintOracle 有一個文檔什麼 performance 什麼裡面講很清楚如何寫 SQL 都很有學問讀清楚那本書就 ok 了如果分區和SQL優化做得好CPU利用率不會太高相對而言數據庫服務器吃內存比較狠應用服務器用 CPU 比內存重要些(<b>singledream</b>)
From:http://tw.wingwit.com/Article/program/Oracle/201311/17020.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.