一些mysql資料庫效能優化方法

2021-07-04 21:41:54 字數 2918 閱讀 4735

一、mysql 資料庫效能優化之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 資料庫效能優化之快取引數優化

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

本文先從 mysql 資料庫io相關引數(快取引數)的角度來看看可以通過哪些引數進行io優化:

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

—eof—

按照 mcsrainbow 朋友的要求,這裡列一下根據以往經驗得到的相關引數的建議值:

mysql資料庫優化的一些記錄

庫表設計時應該為每張表都設定乙個id作為其主鍵,最好是int型 推薦使用unsigned 並設定上自動增加的auto increment,使用varchar型別來當主鍵會使得效能下降。有留意過大型電商 的表字段,使用者編號,訂單編號等都是int型,且訂單編號有一定的規則,具體的沒研究過,除錯一號店介...

效能優化 MySQL資料庫優化

可以從哪幾個方面進行資料庫的優化?如下圖所示 a sql及索引優化 根據需求寫出良好的sql,並建立有效的索引,實現某一種需求可以多種寫法,這時候我們就要選擇一種效率最高的寫法。這個時候就要了解sql優化 b 資料庫表結構優化 根據資料庫的正規化,設計表結構,表結構設計的好直接關係到寫sql語句。c...

mysql 資料庫效能檢視以及一些SQL

主要方法 show status show profile 檢查慢查詢日誌 檢測執行的sql,具體那個位置比較慢 select from phone sts 資料庫版本 select version 查詢sql對資源的占用情況 show profiles 查詢當前sql執行過程中的時間消耗 show...