MySQL效能調優與架構設計-筆記
阿新 • • 發佈:2018-12-31
- MySQL的主要適用場景
- ①Web網站系統:免費開源、安裝配置簡單。
- ②日誌記錄系統:MyISAM實現高效能插入和查詢。
- ③資料倉庫系統:免費支援主從複製。
- InnoDB儲存引擎的特點:
- a. 支援事務安全
- InnoDB是一個事務安全的儲存引擎,其事務安全性主要就是通過線上redo日誌和記錄在表空間中的undo資訊來保證的。redo日誌中記錄了InnoDB所做的所有物理變更的事務資訊,通過redo日誌和undo資訊,InnoDB保證了在任何情況下的事務安全性。
- b. 資料多版本讀取
- c. 支援行鎖(通過索引來完成的)(適合用於高併發場景)
- d. 支援外來鍵
- a. 支援事務安全
- 影響效能的相關因素
- 1、需求是否合理
- 2、資料類別(二進位制多媒體資料、流水佇列資料->用第三方佇列軟體、超大文字資料)
- 3、快取是否有效
- 4、準實時資料和實時資料
- 5、過度依賴Query語句
- 6、重複查詢
- MyISAM的鎖定機制完全是由MySQL提供的表級鎖定實現的。
- InnoDB的鎖定機制
- InnoDB的鎖定是通過在需要鎖定的某行記錄的第一個索引鍵之前和最後一個索引鍵之後的空域空間標記鎖定資訊實現的。InnoDB的這種鎖定實現方式被稱為“NEXT-KEY locking”(間隙鎖),因為Query在執行過程中通過範圍查詢,它會鎖定整個返回內所有的索引鍵值,即使這個鍵值並不存在。
- 除了間隙鎖給InnoDB帶來的負面影響,通過索引實現鎖定的方式還存在其他幾個較大的效能隱患
- a. 當Query無法利用索引的時候,InnoDB會放棄使用行級別鎖定而改用表級別鎖定,造成併發效能降低。
- b. 當Query使用的索引並不包含所有過濾條件時,資料檢索使用到的索引鍵中的資料可能有部分並不屬於該Query的結果集行列,但是也會被鎖定,因為間隙鎖鎖定的是一個範圍,而不是具體的索引鍵。
- c. 當Query在使用索引定位資料的時候,如果使用的索引鍵一樣單訪問的資料行不同(索引只是過濾條件的一部分),它們一樣會被鎖定。
- InnodDB行鎖、表鎖、間隙鎖、死鎖、使用共同索引不同資料的阻塞
- InnoDB行鎖優化
- a. 儘可能讓所有的資料檢索都通過索引完成,避免InnoDB無法通過索引鍵加鎖而升級為表級鎖定。
- b. 合理設計索引,讓InnoDB在索引鍵上面加鎖的時候儘可能準確,儘可能的縮小鎖定範圍,避免不必要的鎖定。
- c. 儘量減少基於範圍的資料檢索過濾條件,避免因為間隙鎖帶來的負面影響而鎖定了不該鎖定的記錄。
- d. 儘量控制事務的大小,減少鎖定的資源量和鎖定時間長度。
- e. 在業務環境允許的情況下,儘量使用較低級別的事務隔離,以減少因為實現事務隔離級別帶來的附加成本。
- 由於InnoDB的行鎖和事務性,所以肯定會產生死鎖,常用的減少死鎖產生概率的建議
- a. 類似業務模組中,儘可能按照相同的訪問順序來訪問,防止產生死鎖。
- b. 在同一個事物中,儘可能做到一次鎖定所有需要的資源,減少死鎖產生的概率。
- c. 對於非常容易產生死鎖的業務部分,可以嘗試使用升級鎖定顆粒度,通過表級鎖定來減少死多產生的概率。
- Query語句優化思路
- a. 優化更需要優化的Query(高併發的Query)
- b. 定位優化物件的效能瓶頸(判斷Query的瓶頸是IO還是CPU)
- c. 明確的優化目標
- d. 從Explain入手
- e. 多使用profile
- f. 永遠使用小結果集驅動大結果集、
- g. 儘可能在索引中完成排序
- h. 只取出自己需要的Columns
- i. 僅僅使用最有效的過濾條件
- j. 儘可能避免複雜的Join和子查詢
- profile判斷Query效能瓶頸是IO還是CPU
- set profiling=1;
- 執行查詢;
- show profiles;檢視queryId
- shwo profile cpu , block for quuery queryId;、
- 分析是否需要建立索引
- a. 頻繁最為查詢條件的欄位應該建立索引
- b. 唯一性太差的欄位不適合單獨建立索引,即使建立了,系統也可能不會使用
- c. 更新非常頻繁的欄位不適合建立索引
- d. 不會出現在where子句中的欄位不需要建立索引
- MySQL中索引的限制
- a. MySQL目前不支援函式索引
- b. 使用不等於的時候MySQL無法使用索引
- c. 過濾欄位使用了函式運算後M有SQL無法使用索引
- d. Join語句中Join條件欄位型別不一致的時候MySQL無法使用索引
- f. 使用like等操作的時候如果條件以萬用字元%開始MySQL無法使用索引
- g. 使用非等值查詢的時候MySQL無法使用Hash索引
- Join的實現原理和優化思路
- 實現原理:Nested Loop Join
- 優化思路:小結果集驅動大結果集或者避免Join連線查詢
- Order By優化
- MySQL中Order By的實現由兩種型別:
- a. 通過有序索引而直接取得有序的資料,不用進行任何排序操作即可得到滿足客戶端要求的有序資料。
- b. 通過MySQL的排序演算法將儲存引擎中返回的資料進行排序然後再將排序後的資料返回給客戶端
- MySQL中Order By的實現由兩種型別:
- Group By優化
- MySQL中Group By的實現有三種方式:
- a. 使用鬆散(Loose)索引掃描實現Group By
- 實際上就是完全利用索引掃描來實現Group By,不需要掃描所有滿足條件的索引鍵即可完成操作得出結果,用Explain分析可以看到 Using index for group-by
- 要使用鬆散索引掃描需要滿足以下幾個條件:
- ♦ Group By條件欄位必須在同一個索引中最前面的連續位置
- ♦ 在使用Group By的同時,只能使用Max和Min這兩個聚合函式
- ♦ 如果引用到了該索引中Group By條件之外的條件欄位的時候,必須以常量形式存在
- b. 使用緊湊索引掃描實現Group By
- 在MySQL 中,MySQL Query Optimizer 首先會選擇嘗試通過鬆散索引掃描來實現GROUP BY 操作,當發現某些情況無法滿足鬆散索引掃描實現GROUP BY 的要求之後,才會嘗試通過緊湊索引掃描來實現。當GROUP BY 條件欄位並不連續或者不是索引字首部分的時候,MySQL Query Optimizer 無法使用鬆散索引掃描,設定無法直接通過索引完成GROUP BY 操作,因為缺失的索引鍵資訊無法得到。但是,如果Query 語句中存在一個常量值來引用缺失的索引鍵,則可以使用緊湊索引掃描完成GROUP BY 操作,因為常量填充了搜尋關鍵字中的“差距”,可以形成完整的索引字首。這些索引字首可以用於索引查詢。而如果需要排序GROUP BY 結果,並且能夠形成索引字首的搜尋關鍵字,MySQL 還可以避免額外的排序操作,因為使用有順序的索引的字首進行搜尋已經按順序檢索到了所有關鍵字。
- c. 使用臨時表實現Group By
- 在優化GROUP BY 的時候還有一個小技巧可以讓我們在有些無法利用到索引的情況下避免filesort 操作,也就是在整個語句最後新增一個以NULL排序(ORDER BY NULL)的子句。
- MySQL中Group By的實現有三種方式: