超詳細 資料庫效能優化(二)

2021-08-26 02:51:12 字數 4559 閱讀 5042

盡量避免 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 的儲存引擎可能是所有關係型資料庫產品中最具有特色的了,不僅可以同時使用多種儲存引擎,而且每種儲存引擎和mysql之間使用外掛程式方式這種非常松的耦合關係。

由於各儲存引擎功能特性差異較大,這篇文章主要是介紹如何來選擇合適的儲存引擎來應對不同的業務場景。

innodb

ndbcluster

盡量避免 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 資料庫效能優化之快取引數優化

資料庫屬於 io 密集型的應用程式,其主要職責就是資料的管理及儲存工作。而我們知道,從記憶體中讀取乙個資料庫的時間是微秒級別,而從一塊普通硬碟上讀取乙個io是在毫秒級別,二者相差3個數量級。所以,要優化資料庫,首先第一步需要優化的就是 io,盡可能將磁碟io轉化為記憶體io。本文先從 mysql 資料庫io相關引數(快取引數)的角度來看看可以通過哪些引數進行io優化:

上面這幾個引數是 mysql 中為了減少磁碟物理io而設計的主要引數,對 mysql 的效能起到了至關重要的作用。

—eof—

超詳細MySQL資料庫優化

資料庫優化一方面是找出系統的瓶頸,提高mysql資料庫的整體效能,而另一方面需要合理的結構設計和引數調整,以提高使用者的相應速度,同時還要盡可能的節約系統資源,以便讓系統提供更大的負荷.1.優化一覽圖 2.優化 筆者將優化分為了兩大類,軟優化和硬優化,軟優化一般是運算元據庫即可,而硬優化則是操作伺服...

資料庫效能優化二 資料庫表優化

資料庫優化包含以下三部分,資料庫自身的優化,資料庫表優化,程式操作優化.此文為第二部分優化 設計規範化表,消除資料冗餘 資料庫正規化是確保資料庫結構合理,滿足各種查詢需要 避免資料庫操作異常的資料庫設計方式。滿足正規化要求的表,稱為規範化表,正規化產生於20世紀 70年代初,一般表設計滿足前三正規化...

資料庫效能優化二 資料庫表優化

優化 設計規範化表,消除資料冗餘 資料庫正規化是確保資料庫結構合理,滿足各種查詢需要 避免資料庫操作異常的資料庫設計方式。滿足正規化要求的表,稱為規範化表,正規化產生於20世紀 70年代初,一般表設計滿足前三正規化就可以,在這裡簡單介紹一下前三正規化 第一正規化 1nf 無重複的列 所謂第一正規化 ...