1. 程式人生 > >加速SQL查詢效能的七大祕訣

加速SQL查詢效能的七大祕訣

  任何平臺的SQL開發者都有自身的困惑,似乎他們一直糾纏在DO WHILE迴圈裡,這個迴圈讓他們不斷地重複同樣的錯誤。這是因為資料庫的發展依然不夠成熟。當然,供應商們也在不斷進步,但是他們還是需要處理更嚴重的問題。併發性,資源管理,空間管理和速度依然制約著SQL開發者對開發平臺的選擇。

  部分問題是因為沒有訣竅可以實現解決這些問題,也沒有任何實踐表明已經解決了這些問題。但是,至少我可以告訴你這裡有一個例外。通常,開發者會找到自己喜歡的方法,儘管這些方法無法實現效能架構和併發性,但是開發者也不會再自找麻煩地去尋找別的方式了。或許這是缺少教育的後果,或許是因為開發者太接近這些程序了,所以就沒辦法認清他們產生的錯誤。可能在本地測試系統上這些查詢程式碼可以執行良好,但是在執行系統上就會產生極大的錯誤。

  我並不期望SQL開發者能成為管理員,但是在寫程式碼的時候,他們必須重視生產問題。如果在開發初期他們就不做這些工作,那麼,DBAs將強制他們回過頭來考慮這個問題,以此同時,使戶也會受到影響。

  我們之所以說調整資料庫是一件藝術性和科學性結合的事情,是因為在應用上來看有很多必須遵守的規則。你在一個系統裡解決的問題,在另一個系統裡依然會出現,反之亦然。在調整資料庫方面沒有萬能的答案,但是你依然不能放棄。

  下面我將總結出在SQL程式設計中容易被忽略的一些注意要點,哪些是可以做的,哪些是不可以做的。這些要點將幫你更加深入地理解DBAs,也可以增強你從面向生產的角度思考程序。

  1.不要用UPDATE代替CASE

  儘管這個問題經常被忽略,但是卻是一個很普遍的問題。很多開發者都會忽略這個問題,因為使用UPDATE看起來是一個具有邏輯性的自然流。

  在這種情況下,例如:你插入一個臨時表格,在存在另一個值的時候,讓它顯示某個值。你要從客戶表中按順序列出超過10萬美金的人,以便把他們設定為“首選”。這時,你就要把資料插入表格中,執行UPDATEA命令來設定CustomerRank列,來順序定義那些超過10萬美金的人。問題是,UPDATE命令已經被記錄了,這就意味著針對每一個表寫入你都要進行兩次操作。當然,針對這個過程可以使用SQL查詢語言本身的CASE語句。它將測試每一行是否符合總體條件,並在寫入表格前,給它一個“首選”的標籤。這種效能的提高是驚人的。

  2.不要盲目使用程式碼

  這個也是很普遍的。這很容易複製別人的程式碼,因為你知道它這段程式碼可以查詢到你需要的資料。問題是,很多時候複製別人的程式碼會讓你得到很多你不需要的額外資料。但是很少有開發者有功夫去挑選這些資料。所以他們也只是通過這些程式碼得到了需要資料的父集。這樣的程式碼通常是以外部連結的方式或者是在WHERE語句中出現。所以說如果你有針對性地修改程式碼,SQL的效能就會得到大大的提升。

  3.只查詢對你游泳的列

  這個問題和第二個問題類似,但是,是針對列來講的。用SELECT * 查詢,而不是分別對每列查詢在程式碼實現方面也簡單地多。但是這時,問題再一次出現,你再次得到了比你需要的資料多得多的資料。我已經無數次地看到這種現象發生了。開發者用SELECT * 語句查詢一個120列、幾百萬行的表以後最後只得到了3到5行的有用資料。在這一點上,你不是僅僅查詢了比你所需要的資料多的資料,你還從別的程序中搶奪了資源,降低了整體速度。

  4.不要做兩次查詢

  還有一個常見的現象是:寫一個從擁有無數行的表裡取資料的儲存程序。開發者需要查詢到符合這樣以下條件的使用者:住在加利福尼亞州,收入超過$40,000。這時,他把住在加利福尼亞州的客戶查出來放到一張零時表中,然後把收入在$40,000以上的客戶查出來放到另一張零時表中。最後,他合併這兩個表得到最終的查詢結果。然後,通過更小的資料集,來加強後續步驟。

  你在開玩笑吧?這個查詢應該是一個單一的查詢,可是,你卻對一個如此大型的表進行了兩次查詢。不要再做這樣的傻事了:對大型表格說,儘可能地只進行一次查詢。這時,你會發現你的程式執行起來效率更高了。

  稍微不同的地方是,當我們需要通過幾個步驟查詢一個大型表的子集時,它將導致對大型表的多次查詢。一定要通過查詢子集避免這種事情的發生。

  5.確定使用臨時表的時機。

  這是一個比較難以處理的問題,但是你可以從這裡得到很多好處。很多情況下,都是可以使用臨時表的,比如:在避免兩次從一個大型表格裡查詢時。在連線兩個表格的時候,你也可以使用臨時表來大大降低處理程式所佔用的記憶體。如果你必須把一個表合併到一個大型表格中,你可以通過先從大型表中檢索出你所需要的資料合併到臨時表中,然後用把這些資料合併的方法來優化命令。如果在程序中,你必須對同一個表進行同樣的合併的時候,臨時表是一個非常有用的方式。

  6.必須預存資料。

  這是我比較喜歡的一個話題,因為這是一個比較容易被忽略的老方法。如果你有一個報告或者一個程序,它們需要向一個大型表裡做型別的合併,這時,如果你能通過提前合併表格或者是插入表格的方法來預存資料,這將對你的操作大大有益。

  一般情況下,你是不能使用這個技巧的。但是,如果你可以,你會發現這將是一個非常完美的節約伺服器資源的方法。

  注意到這樣的問題,一般開發者通過關注查詢本身而避開這樣的合併問題,建立一個只可見的合併,以致於不能一而再,再而三地定義它們的合併環境。通過預存資料,你只需執行一次合併,同時別人也避免了大型的合併。我非常喜歡用這種方法,大多數情況下,有很多流行表總是執行合併,所以沒有任何理由說不能預存資料。

  7,分批地刪除和更新。

  還有一個常被忽略的簡單技巧。如果你的操作錯誤,從一個大型表裡刪除和更新大量的資料將是一個噩夢。問題是這兩個命令執行起來就像是一個命令,如果你需要放棄他們,或者如果你在工作的時候系統發生了什麼事情,系統就必須從頭開始所有命令的執行。這會花費很多時間。這些操作也會妨礙別的命令的執行,甚至會成為整個系統的瓶頸。

  解決這個問題的辦法是,小批量地刪除和更新資料。可以通過兩種方式來解決這個問題:一,如果命令的執行因為任何原因被終止,那就必須有一小部分行從頭開始執行,所以資料庫恢復得將會快得多。二,當更少的資料被存在了硬碟上時,別的命令也可以做一些工作,所以併發性就被大大地優化了。

  按照這個指示,很多開發者企圖在一天之內把這些刪除和更新操作完成。但是,這並不是總是正確的,特別是當你在存檔的時候。只要你需要,你可以儘可能地擴充套件這些炒作,而且這些小批量的資料也可以幫助你完成這些。如果你可以花費更多的時間來做更多的操作,那麼就花費一些多餘的時間吧,同時不要讓你的系統停下來。

  當你寫程式碼來優化你的SQL效能的時候,在任何你可以遵守這些事項的時候,就去遵守它們。但是,請分別評價這些解決方法來看看哪種方法是最有效的,可以說沒有一個萬能的或者是固定的方法來解決這些問題。你將會發現很多竅門都是和ikyi提高併發性,並可以讓整體執行通暢的。同時,你也會注意到這些物理實現會從這個供應商傳遞到下一個供應商,這些概念和問題將會存在每一個SQL平臺上。