一、mysql 資料庫效能優化之sql優化
注:這篇文章是以 mysql 為背景,很多內容同時適用於其他關係型資料庫,需要有一些索引知識為基礎
盡量少 join
mysql 的優勢在於簡單,但這在某些方面其實也是其劣勢。mysql 優化器效率高,但是由於其統計資訊的量有限,優化器工作過程出現偏差的可能性也就更多。對於複雜的多表 join,一方面由於其優化器受限,再者在 join 這方面所下的功夫還不夠,所以效能表現離 oracle 等關係型資料庫前輩還是有一定距離。但如果是簡單的單錶查詢,這一差距就會極小甚至在有些場景下要優於這些資料庫前輩。
盡量少排序
排序操作會消耗較多的 cpu 資源,所以減少排序可以在快取命中率高等 io 能力足夠的場景下會較大影響 sql 的響應時間。
對於mysql來說,減少排序有多種辦法,比如:
盡量避免 select *
很多人看到這一點後覺得比較難理解,上面不是在誤區中剛剛說 select 子句中字段的多少並不會影響到讀取的資料嗎?
是的,大多數時候並不會影響到 io 量,但是當我們還存在 order by 操作的時候,select 子句中的字段多少會在很大程度上影響到我們的排序效率,這一點可以通過我之前一篇介紹 mysql order by 的實現分析 的文章中有較為詳細的介紹。
此外,上面誤區中不是也說了,只是大多數時候是不會影響到 io 量,當我們的查詢結果僅僅只需要在索引中就能找到的時候,還是會極大減少 io 量的。
盡量用 join 代替子查詢
雖然 join 效能並不佳,但是和 mysql 的子查詢比起來還是有非常大的效能優勢。mysql 的子查詢執行計畫一直存在較大的問題,雖然這個問題已經存在多年,但是到目前已經發布的所有穩定版本中都普遍存在,一直沒有太大改善。雖然官方也在很早就承認這一問題,並且承諾盡快解決,但是至少到目前為止我們還沒有看到哪乙個版本較好的解決了這一問題。
盡量少 or
當 where 子句中存在多個條件以「或」並存的時候,mysql 的優化器並沒有很好的解決其執行計畫優化問題,再加上 mysql 特有的 sql 與 storage 分層架構方式,造成了其效能比較低下,很多時候使用 union all 或者是union(必要的時候)的方式來代替「or」會得到更好的效果。
盡量用 union all 代替 union
union 和 union all 的差異主要是前者需要將兩個(或者多個)結果集合並後再進行唯一性過濾操作,這就會涉及到排序,增加大量的 cpu 運算,加大資源消耗及延遲。所以當我們可以確認不可能出現重複結果集或者不在乎重複結果集的時候,盡量使用 union all 而不是 union。
盡量早過濾
這一優化策略其實最常見於索引的優化設計中(將過濾性更好的字段放得更靠前)。
在 sql 編寫中同樣可以使用這一原則來優化一些 join 的 sql。比如我們在多個表進行分頁資料查詢的時候,我們最好是能夠在乙個表上先過濾好資料分好頁,然後再用分好頁的結果集與另外的表 join,這樣可以盡可能多的減少不必要的 io 操作,大大節省 io 操作所消耗的時間。
避免型別轉換
這裡所說的「型別轉換」是指 where 子句**現 column 欄位的型別和傳入的引數型別不一致的時候發生的型別轉換:
優先優化高併發的 sql,而不是執行頻率低某些「大」sql
對於破壞性來說,高併發的 sql 總是會比低頻率的來得大,因為高併發的 sql 一旦出現問題,甚至不會給我們任何喘息的機會就會將系統壓跨。而對於一些雖然需要消耗大量 io 而且響應很慢的 sql,由於頻率低,即使遇到,最多就是讓整個系統響應慢一點,但至少可能撐一會兒,讓我們有緩衝的機會。
從全域性出發優化,而不是片面調整
sql 優化不能是單獨針對某乙個進行,而應充分考慮系統中所有的 sql,尤其是在通過調整索引優化 sql 的執行計畫的時候,千萬不能顧此失彼,因小失大。
盡可能對每一條執行在資料庫中的sql進行 explain
優化 sql,需要做到心中有數,知道 sql 的執行計畫才能判斷是否有優化餘地,才能判斷是否存在執行計畫問題。在對資料庫中執行的 sql 進行了一段時間的優化之後,很明顯的問題 sql 可能已經很少了,大多都需要去發掘,這時候就需要進行大量的 explain 操作收集執行計畫,並判斷是否需要進行優化。
二、mysql 資料庫效能優化之表結構
很多人都將資料庫設計正規化作為資料庫表結構設計「聖經」,認為只要按照這個正規化需求設計,就能讓設計出來的表結構足夠優化,既能保證效能優異同時還能滿足擴充套件性要求。殊不知,在n年前被奉為「聖經」的資料庫設計3正規化早就已經不完全適用了。這裡我整理了一些比較常見的資料庫表結構設計方面的優化技巧,希望對大家有用。
由於mysql資料庫是基於行(row)儲存的資料庫,而資料庫操作 io 的時候是以 page(block)的方式,也就是說,如果我們每條記錄所占用的空間量減小,就會使每個page中可存放的資料行數增大,那麼每次 io 可訪問的行數也就增多了。反過來說,處理相同行數的資料,需要訪問的 page 就會減少,也就是 io 操作次數降低,直接提公升效能。此外,由於我們的記憶體是有限的,增加每個page中存放的資料行數,就等於增加每個記憶體塊的快取資料量,同時還會提公升記憶體換中資料命中的機率,也就是快取命中率。
上面幾點的優化都是為了減少每條記錄的儲存空間大小,讓每個資料庫中能夠儲存更多的記錄條數,以達到減少 io 操作次數,提高快取命中率。下面這個優化建議可能很多開發人員都會覺得不太理解,因為這是典型的反正規化設計,而且也和上面的幾點優化建議的目標相違背。
三、mysql 資料庫效能優化之索引優化
大家都知道索引對於資料訪問的效能有非常關鍵的作用,都知道索引可以提高資料訪問效率。
為什麼索引能提高資料訪問效能?他會不會有「***」?是不是索引建立越多,效能就越好?到底該如何設計索引,才能最大限度的發揮其效能?
這篇文章主要是帶著上面這幾個問題來做乙個簡要的分析,同時排除了業務場景所帶來的特殊性,請不要糾結業務場景的影響。
下面我們通過上面這個生活中的小示例,來分析一下索引,看看能的出哪些結論?
MySQL 資料庫效能優化之索引優化
資料庫效能優化專題 系列的第三篇文章 mysql 資料庫效能優化之索引優化 大家都知道索引對於資料訪問的效能有非常關鍵的作用,都知道索引可以提高資料訪問效率。為什麼索引能提高資料訪問效能?他會不會有 是不是索引建立越多,效能就越好?到底該如何設計索引,才能最大限度的發揮其效能?這篇文章主要是帶著上面...
MySQL 資料庫效能優化之索引優化
大家都知道索引對於資料訪問的效能有非常關鍵的作用,都知道索引可以提高資料訪問效率。為什麼索引能提高資料訪問效能?他會不會有 是不是索引建立越多,效能就越好?到底該如何設計索引,才能最大限度的發揮其效能?這篇文章主要是帶著上面這幾個問題來做乙個簡要的分析,同時排除了業務場景所帶來的特殊性,請不要糾結業...
MySQL資料庫效能優化之索引優化
大家都知道索引對於資料訪問的效能有非常關鍵的作用,都知道索引可以提高資料訪問效率。為什麼索引能提高資料訪問效能?他會不會有 是不是索引建立越多,效能就越好?到底該如何設計索引,才能最大限度的發揮其效能?這篇文章主要是帶著上面這幾個問題來做乙個簡要的分析,同時排除了業務場景所帶來的特殊性,請不要糾結業...