Mysql 查詢語句優化原則

2021-08-13 08:55:31 字數 3899 閱讀 4447

mysql是web開發人員使用最多的資料庫之一,在**系統整體優化的過程中,針對資料庫的優化又是最重要的乙個環節,

一般來說,query 語句的優化思路和原則主要提現在以下幾個方面:

1. 優化更需要優化的query;

2. 定位優化物件的效能瓶頸;

3. 明確的優化目標;

4. 從explain 入手;

5. 多使用profile

6. 永遠用小結果集驅動大的結果集;

7. 盡可能在索引中完成排序;

8. 只取出自己需要的columns;

9. 僅僅使用最有效的過濾條件;

10. 少使用join 和子查詢;

什麼樣的query 是更需要優化? 對於這個問題我們需要從對整個系統的影響來考慮。

什麼query 的優化能給系統整體帶來更大的收益,就更需要優化。

一般來說,高併發低消耗(相對)的query 對整個系統的影響遠比低併發高消耗的query 大。我們可以通過以下乙個非常簡單的案例分析來充分說明問題。

假設有乙個query 每小時執行10000 次,每次需要20 個io。另外乙個query 每小時執行10 次,每次需要20000 個io。

我們先通過io 消耗方面來分析。可以看出,兩個query 每小時所消耗的io 總數目是一樣的,都是200000 io/小時。

假設我們優化第乙個query,從20 個io 降低到18 個io,也就是僅僅降低了2 個io,則我們節省了2 * 10000 = 20000 (io/小時)。

而如果希望通過優化第二個query 達到相同的效果,我們必須要讓每個query 減少20000 / 10 = 2000 io。

我想大家都會相信讓第乙個query 節省2 個io遠比第二個query 節省2000 個io 來的容易。

其次,如果通過cpu 方面消耗的比較,原理和上面的完全一樣。

只要讓第乙個query 稍微節省一小塊資源就可以讓整個系統節省出一大塊資源,尤其是在排序,分組這些對cpu 消耗比較多的操作中尤其突出。

最後,我們從對整個系統的影響來分析。

乙個頻繁執行的高併發query 的危險性比乙個低併發的query 要大很多。

當乙個低併發的query 走錯執行計畫,所帶來的影響主要只是該query 的請求者的體驗會變差,對整體系統的影響並不會特別的突出,之少還屬於可控範圍。

但是,如果我們乙個高併發的query 走錯了執行計畫,那所帶來的後可很可能就是災難性的,很多時候可能連自救的機會都不給你就會讓整個系統crash 掉。

曾經我就遇到這樣乙個案例,系統中乙個併發度較高的query 語句走錯執行計畫,系統頃刻間crash,甚至我都還沒有反應過來是怎麼回事。當重新啟動資料庫提供服務後,系統負載立刻直線飆公升,甚至都來不及登入資料庫檢視當時有哪些active 的執行緒在執行哪些query。

如果是遇到乙個併發並不太高的query 走錯執行計畫,至少我們還可以控制整個系統不至於系統被直接壓跨,甚至連問題根源都難以抓到。

定位優化物件的效能瓶頸

當我們拿到一條需要優化的query 之後,第一件事情是什麼?是反問自己,這條query 有什麼問題?我為什麼要優化他?

只有明白了這些問題,我們才知道我們需要做什麼,才能夠找到問題的關鍵。

而不能就只是覺得某個query 好像有點慢,需要優化一下,然後就開始乙個乙個優化方法去輪番嘗試。

這樣很可能整個優化過程會消耗大量的人力和時間成本,甚至可能到最後還是得不到乙個好的優化結果。

這就像看病一樣,醫生必須要清楚的知道我們病的根源才能對症下藥。如果只是知道我們什麼地方不舒服,然後就開始通過各種藥物嘗試**,那這樣所帶來的後果可能就非常嚴重了。

所以,在拿到一條需要優化的query 之後,我們首先要判斷出這個query 的瓶頸到底是io 還是cpu。到底是因為在資料訪問消耗了太多的時間,還是在資料的運算(如分組排序等)方面花費了太多資源?

一般來說,在mysql 5.0 系列版本中,我們可以通過系統自帶的profiling 功能很清楚的找出乙個query 的瓶頸所在。

當然,如果讀者朋友為了使用mysql 的某些在5.1 版本中才有的新特性(如partition,event 等)亦或者是比較喜歡嘗試新事務而早早使用的mysql 5.1 的預發布版本,可能就沒辦法使用這個功能了,因為該功能在mysql5.1 系列剛開始的版本中並不支援,不過讓人非常興奮的是該功能在最新出來的mysql 5.1 正式版(5.1.30)又已經提供了。

而如果讀者朋友正在使用的mysql 是4.x 版本,那可能就只能通過自行分析query 的各個執行步驟,找到效能損失最大的地方。

明確的優化目標

當我們定為到了一條query 的效能瓶頸之後,就需要通過分析該query 所完成的功能和query 對系統的整體影響制訂出乙個明確的優化目標。

沒有乙個明確的目標,優化過程將是乙個漫無目的而且低效的過程,也很難達收到乙個理想的效果。

尤其是對於一些實現應用中較為重要功能點的query 更是如此。

如何設定優化目標?

這可能是很多人都非常頭疼的問題,對於我自己也一樣。要設定乙個合理的優化目標,不能過於理想也不能放任自由,確實是一件非常頭疼的事情。

一般來說,我們首先需要清楚的了解資料庫前的整體狀態,同時也要清楚的知道資料庫中與該query 相關的資料庫物件的各種資訊,而且還要了解該query 在整個應用系統中所實現的功能。了解了資料庫整體狀態,我們就能知道資料庫所能承受的最大壓力,也就清楚了我們能夠接受的最悲觀情況。把握了該query 相關資料庫物件的資訊,我們就應該知道實現該query 的消耗最理想情況下需要消耗多少資源,最糟糕又需要消耗多少資源。

最後,通過該query 所實現的功能點在整個應用系統中的重要地位,我們可以大概的分析出該query 可以占用的系統資源比例,而且我們也能夠知道該query 的效率給客戶帶來的體驗影響到底有多大。

當我們清楚了這些資訊之後,我們基本可以得出該query 應該滿足的乙個效能範圍是怎樣的,這也就是我們的優化目標範圍,然後就是通過尋找相應的優化手段來解決問題了。

如果該query 實現的應用系統功能比較重要,我們就必須讓目標更偏向於理想值一些,即使在其他某些方面作出一些讓步與犧牲,比如調整schema 設計,調整索引組成等,可能都是需要的。

而如果該query 所實現的是一些並不是太關鍵的功能,那我們可以讓目標更偏向悲觀值一些,而盡量保證其他更重要的query 的效能。這種時候,即使需要調整商業需求,減少功能實現,也不得不應該作出讓步。

從explain 入手

現在,優化目標也已經明確了,自然是奧開始動手的時候了。我們的優化到底該從何處入手呢?

答案只有乙個,從explain 開始入手。為什麼?因為只有explain 才能告訴你,這個query 在資料庫中是

以乙個什麼樣的執行計畫來實現的。

但是,有一點我們必須清楚,explain 只是用來獲取乙個query 在當前狀態的資料庫中的執行計畫,在優化動手之前,我們比需要根據優化目標在自己頭腦中有乙個清晰的目標執行計畫。

只有這樣,優化的目標才有意義。乙個優秀的sql 調優人員(或者成為sql performance tuner),在優化任何乙個sql 語句之前,都應該在自己頭腦中已經先有乙個預定的執行計畫,然後通過不斷的調整嘗試,再借助explain 來驗證調整的結果是否滿足自己預定的執行計畫。對於不符合預期的執行計畫需要不斷分析query 的寫法和資料庫物件的資訊,繼續調整嘗試,直至得到預期的結果。

當然,人無完人,並不一定每次自己預設的執行計畫都肯定是最優的,在不斷調整測試的過程中,如果發現mysql optimizer 所選擇的執行計畫的實際執行效果確實比自己預設的要好,我們當然還是應該選擇使用mysql optimizer 所生成的執行計畫。

上面的這個優化思路,只是給大家指了乙個優化的基本方向,實際操作還需要讀者朋友不斷的結合具體應用場景不斷的測試實踐來體會。當然也並不一定所有的情況都非要嚴格遵循這樣乙個思路,規則是死的,人是活的,只有更合理的方法,沒有最合理的規則。

在了解了上面這些優化的基本思路之後,我們再來看看優化的幾個基本原則。

mysql語句優化原則 MySQL語句優化的原則

1 使用索引來更快地遍歷表。預設情況下建立的索引是非群集索引,但有時它並不是最佳的。在非群集索引下,資料在物理上隨機存放在資料頁上。合理的索引設計要建立在對各種查詢的分析和 上。一般來說 a.有大量重複值 且經常有範圍查詢 和order by group by發生的列,可考慮建立群集索引 b.經常同...

mysql語句優化原則 mysql語句優化原則

有時候發現資料量大的時候查詢起來效率就比較慢了,學習一下mysql語句優化的原則,自己在正常寫sql的時候還沒注意到這些,先記錄下來,慢慢一點一點的學,加油!這幾篇部落格寫的都可以 使用索引的原則 1.最左字首匹配原則。mysql會一直向右匹配直到遇到範圍查詢 不會用到b的索引 where a 1 ...

mysql語句優化原則 MySQL語句優化的原則

mysql語句優化的原則 mysql語句優化的原則 1 使用索引來更快地遍歷表。預設情況下建立的索引是非群集索引,但有時它並不是最佳的。在非群集索引下,資料在物理上隨機存放在資料頁上。合理的索引設計要建立在對各種查詢的分析和 上。一般來說 a.有大量重複值 且經常有範圍查詢 和order by gr...