本文出自頭條號老王談運維,轉載請說明出處。
MySQL 數據庫瓶頸對 DBA 程序員而言,是非常棘手的問題。要正確的優化SQL,我們需要快速定位能性的瓶頸點,也就是說快速找到我們SQL主要的開銷在哪里?下面小編將從數據庫數據庫性能優化的目標和方法兩方面闡述如何通過性能調優突破 MySQL 數據庫性能瓶頸。

優化目標
減少 IO 次數
IO永遠是數據庫最容易瓶頸的地方,這是由數據庫的職責所決定的,大部分數據庫操作中超過90%的時間都是 IO 操作所占用的,減少 IO 次數是 SQL 優化中需要第一優先考慮,當然,也是收效最明顯的優化手段。
降低 CPU 計算
除了 IO 瓶頸之外,SQL優化中需要考慮的就是 CPU 運算量的優化了。order by, group by,distinct … 都是消耗 CPU 的大戶(這些操作基本上都是 CPU 處理內存中的數據比較運算)。當我們的 IO 優化做到一定階段之后,降低 CPU 計算也就成為了我們 SQL 優化的重要目標。

優化方法
改變 SQL 執行計划
明確了優化目標之后,我們需要確定達到我們目標的方法。對於 SQL 語句來說,達到上述2個目標的方法其實只有一個,那就是改變 SQL 的執行計划,讓他盡量“少走彎路”,盡量通過各種“捷徑”來找到我們需要的數據,以達到 “減少 IO 次數” 和 “降低 CPU 計算” 的目標
order by 一定需要排序操作
我們知道索引數據實際上是有序的,如果我們的需要的數據和某個索引的順序一致,而且我們的查詢又通過這個索引來執行,那么數據庫一般會省略排序操作,而直接將數據返回,因為數據庫知道數據已經滿足我們的排序需求了。
實際上,利用索引來優化有排序需求的 SQL,是一個非常重要的優化手段
盡量少 join
MySQL 的優勢在於簡單,但這在某些方面其實也是其劣勢。MySQL 優化器效率高,但是由於其統計信息的量有限,優化器工作過程出現偏差的可能性也就更多。對於復雜的多表 Join,一方面由於其優化器受限,再者在 Join 這方面所下的功夫還不夠,所以性能表現離 Oracle 等關系型數據庫前輩還是有一定距離。但如果是簡單的單表查詢,這一差距就會極小甚至在有些場景下要優於這些數據庫前輩。
盡量少排序
排序操作會消耗較多的 CPU 資源,所以減少排序可以在緩存命中率高等 IO 能力足夠的場景下會較大影響 SQL 的響應時間。
對於MySQL來說,減少排序有多種辦法,比如:
通過利用索引來排序的方式進行優化:減少參與排序的記錄條數,非必要不對數據進行排序
避免使用耗費資源的操作,帶有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL語句會啟動SQL引擎 執行,耗費資源的排序(SORT)功能。DISTINCT需要一次排序操作, 而其他的至少需要執行兩次排

盡量用 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進行 explain
優化 SQL,需要做到心中有數,知道 SQL 的執行計划才能判斷是否有優化余地,才能判斷是否存在執行計划問題。在對數據庫中運行的 SQL 進行了一段時間的優化之后,很明顯的問題 SQL 可能已經很少了,大多都需要去發掘,這時候就需要進行大量的 explain 操作收集執行計划,並判斷是否需要進行優化。

優先優化高並發的 SQL,而不是執行頻率低某些“大”SQL
對於破壞性來說,高並發的 SQL 總是會比低頻率的來得大,因為高並發的 SQL 一旦出現問題,甚至不會給我們任何喘息的機會就會將系統壓跨。而對於一些雖然需要消耗大量 IO 而且響應很慢的 SQL,由於頻率低,即使遇到,最多就是讓整個系統響應慢一點,但至少可能撐一會兒,讓我們有緩沖的機會。
從全局出發優化,而不是片面調整
SQL 優化不能是單獨針對某一個進行,而應充分考慮系統中所有的 SQL,尤其是在通過調整索引優化 SQL 的執行計划的時候,千萬不能顧此失彼,因小失大。
總結
對於MySQL數據庫進行性能優化非常重要,一方面可以提升資源使用率,另一方面可以提升業務訪問速度提升用戶體驗。除此之外為了保障業務正常穩定的運行,同樣重要的是能夠及時的發現數據庫存在的性能瓶頸,例如:數據庫 IOPS 使用率過高,數據庫存在存在慢查詢等...

對於互聯網業務的實時監控和及時告警,推薦大家一個實用的運維工具——王教授,是一個 SaaS 化的在線雲計算管理及協作平台,你只需綁定對應雲賬號的AcessKey即可隨時查看到該賬戶下所有資產狀況,同時他還會對賬號下資產“健康狀況”做出診斷,及時發出告警並且給出優化建議。例如:

提示雲數據庫RDS存在慢查詢

提示雲數據庫存在錯誤日志
有需要的同學可以點擊文末王教授二維碼查看詳情~