慢SQL優化

一個SQL執行時間過長,長期佔用MySQL會話連接,會耗盡連接數。這樣其他請求就無法建立連接。一個SQL返回時間過長,對用戶體驗也會造成影響。另外,慢SQL會消耗數據庫實例的資源,進一步把其他正常SQL也變成慢SQL。可能造成數據庫實例失去響應。畢竟,雪崩的時候,沒有沒有一片雪花是無辜的。

代碼層面的優化,受不同的編程語言、技術選型等因素的影響,解決方案也會有一定的差異。但是SQL優化則具備比較高的通用性。雖然不同廠商實現的數據庫管理軟件在執行SQL時會有一定的差異,但是都基於標準SQL。

慢SQL的判定

通常來說,執行時間超過1s的SQL我們就認爲這是一條慢SQL。我們可以從MySQL的慢查詢日誌中收集。
但是,僅憑執行時間判斷是不夠的。如果當前MySQL實例的負載很高,即使是一條按主鍵查詢的簡單SQL也會變成慢SQL。也需要綜合其他因素進行判斷,比如平均執行時間、掃描行數、執行次數。

MySQL的工作原理與慢的原因

MySQL使用B+樹來組織數據和索引。四層的B+樹,已經能夠組織足夠多的數據了。查詢每一層的節點,都需要一次IO操作。而一次磁盤的操作,大概是10ms。因此,如果是走了索引,比如說是主鍵索引,最壞的情況下四次IO操作就可以取到數據了。50ms就夠了。

慢SQL優化的一般步驟

優化,主要是找冗餘。可以從減少IO操作和耗時計算兩個方面考慮。
SQL的調試不像靜態編程語言調試那樣,可以設置斷點。在MySQL中可以使用EXPLAIN命令查看SQL的執行情況。
執行優化後的sql時,爲了得到準確的執行時間,加入SQL_NO_CACHE指令,避免SQL執行時間受到MySQL緩存的影響。另外,MySQL執行某個SQL後,會把相應的數據加載到緩衝區進行預熱。因此初次執行的時間跟多次執行的時間會有一定的差別。
那些是需要優化的慢SQL。

慢SQL的常見類型

索引問題

  • 查詢沒有走索引。如果一個表的數據量比較大,但是沒有索引,會造成慢查詢。這種類型的問題往往是某些場景沒有考慮到,或者項目初期沒有這麼大的數據量,對查詢的影響不大。一般這種問題可以通過工具來輔助發現問題sql。
  • 索引的區分度不高。索引設計的不好,沒辦法有效的過濾掉不符合查詢條件的記錄。此時數據庫仍然需要掃描大量的行。性別字段、表示開關狀態的字段,加了索引也沒有太大的作用。
  • 問題索引。添加了索引,查詢不一定就會變快。重複的索引。索引合併的情況。
  • 索引的選擇問題。MySQL沒有選擇最優的索引。此時可以選擇強制走某個可能最優的索引,或者忽略某個最壞的索引。
  • 排序。
  • 索引無法命中的問題。類型不匹配,導致隱式類型轉換。MySQL不支持函數索引,某個字段使用了函數導致該字段的索引無法使用。

分頁查詢

  • 查詢結果一次返回。隨着業務量的增長,一次返回的數據量太大會造成性能問題。
  • 數據量太大時,分頁的查詢也很慢。分頁查詢可以減少數據庫單次查詢的數據量,從而緩解性能壓力。但是,MySQL的分頁機制下,即使是分頁數據庫也會把符合條件的數據都拉取出來,然後返回指定分頁區間的數據。隨着分頁的增長,查詢依然會越來越慢。此時,可以先查詢符合條件的記錄主鍵,然後根據主鍵查詢相應的行記錄。

子查詢

子查詢會創建臨時表,一定程度上會降低數據庫實例的性能。

  • 使用IN、EXISTS語法時,參與查詢的行數不宜過多,100以內。多的話分頁查詢。
  • 在應用層拆分。在代碼層面先獲取子查詢的結果,然後再將其作爲外層SQL的條件,分步實現。
  • 將子查詢改爲連表查詢

連表查詢

連接多個表的問題。

  • 用數據量較小的表驅動數據量較多的表。
  • 移除掉沒必要的表。在select和where語句中都沒有涉及到的表,是不需要連接的。
  • 拆分爲多個SQL。先查詢主表,然後再根據連接字段分別查詢對應的表的數據。
  • 避免join操作。在對應的表上將某些常用字段冗餘一份,可以減少不必要的連接。或者保存一個json字符串,將所需的結果都放入其中。換句話說,就是使用NoSQL的方式聚合對象信息。

常見的優化策略

SQL優化只是性能優化的一個環節。應用層的優化、MySQL實例的配置調優等方面也是一個提升性能的點。
如果一個SQL已經沒有優化空間了,那該如何處理?

  • 將難以優化的SQL隔離開,在從庫中執行。
  • 時間段上將相關任務異步化,優先級降低。
  • 監控慢SQL執行進程,超過一定時長,殺死該進程。
  • 另一方面,有些離線分析的業務,不應該使用MySQL。這些邏輯應該在數據分析套件中去實現。

SQL優化的自動化

對於固定的常見類型,目前已有部分成熟的工具來輸出優化建議。
慢SQL優化流程化管理

這些優化工具安裝依賴比較多,建議使用docker部署。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章