淺析如何定位,排除和避免MySQL性能故障
首先是如何檢查SQL的效率.
1.善用explain:
設計SQL后,應使用explain命令檢查SQL,看是否使用到索引,是否存在filesort,重點檢查檢索的行數(rows)是否太大。
一般來說.
rows<1000,是在可接受的范圍內的。
rows在1000~1w之間,在密集訪問時可能導致性能問題,但如果不是太頻繁的訪問(頻率低于1分鐘一次),又難再優化的話,可以接受,但需要注意觀察
rows大于1萬時,應慎重考慮SQL的設計,優化SQL,優化db,一般來說不允許頻繁運行(頻率低于1小時一次)。
rows達到10w級別時,堅決不能做為實時運行的SQL。但導數據場合除外,但導數據必須控制好時間,頻度。
explain SQL語句應該是日常開發中的習慣動作,有時explain出來的結果,可能會出于偏離設計的意料之外,所以
**強烈建議在設計SQL,尤其是稍微復雜的SQL時,一定要在測試環境甚至是實際環境上預先進行explain**
2.MySQL慢查詢日志
一般應打開MySQL的慢查詢日志(在my.cnf中加入log_slow_queries和long_query_time兩個參數),會記錄所有查詢持續時間超過long_query_time的SQL語句,把這些語句log下來之后,再一一分析(explain)優化。
3.監視當前進程
登陸MySQL,使用show processlist查看正在運行的SQL語句,如果正在運行的語句太多,運行時間太長,表示MySQL效率有問題。必要的時候可以將對應的進程kill掉。
4.系統命令
使用top/vmstat等系統命令來檢查MySQL進程占用的cpu,內存,以及磁盤IO量。
對MySQL優化的文章很多,這里只提幾點平時工作中比較常用到的方法。
◆建表時,顯式指定使用innodb數據庫引擎,而不是myisam,myisam引擎的鎖是表鎖,讀鎖和寫鎖是互斥的,讀寫操作是串行的,鎖沖突會嚴重影響并發.而innodb提供行級鎖,能提供較好的并發表現,在我們的業務場景里,也不會引起死鎖。
◆善用索引,對SQL語句where條件里使用到的字段,合理建立索引。雖然對表建立索引一定程度上會影響寫入效率,但在表數據規模不大,寫入壓力不是特別高的情況下,索引帶來的好處是更多的。
◆當SQL語句是由代碼動態生成的,如在運行時根據用戶操作加入不同的where參數,應在測試階段對SQL生成的典型情況和邊界情況進行測試,看是否有可能造成性能問題。并應適當生成一些日志,供提取最終生成的SQL進行效率分析。
◆對數據應合理分庫分表,由應用層去動態的選擇庫和表。MySQL的innodb表雖然理論上可以裝海量的數據,但在我們的業務場景下,數據控制在500w以下會比較合理,追求性能的話,最好控制在200w以下,合理索引。
◆需要聯合查詢時善用left join/right join而不是直接多表聯合,怎么用,查manul ^_^
◆盡量不要使用select套select的復合查詢,如果能拆開,盡量拆開,多條精悍的SQL,組合起來可能就是一條龐大的SQL,應該避免。
◆善用cache,將不常修改的,數據量有限的,又是被密集查詢的信息,加載到cache里,可以有效的降低數據庫壓力。在一般的業務場景里,推薦使用開源memcache,簡單高效。
◆如果一些邏輯可以放到應用層去完成,可以考慮放到應用層去完成。但如果將SQL邏輯分拆到應用層可能導致對數據更頻繁的訪問的話,那么需要考慮修改應用邏輯,數據結構,或回到合理的聯合查詢上來。
比如某些數據的排序可以load到php數組里,再sort.又比如需要查詢A,B兩個表,A表里的數據是B表里某個字段的對照說明(如A:t_service表,B.t_task表),A表數據量有限,可以做聯合查詢,也可以先將A表先load到進程或內存里,用hash結構cache起來,再查B表,然后在cache里依次查詢hash,獲得對照說明。
◆關于導數據和統計性查詢.導數據在計算和磁盤io上對數據庫壓力都會很大,應在時間和空間上合理分攤數據庫壓力如果需要導出批量的特定數據做分析,應建立專供數據分析的數據庫服務器,或者建立臨時庫表,先導出數據,再在上面做分析運算。
導數據等可能引起批量數據讀取的操作,應建立定時任務,在數據庫不繁忙的時段(凌晨1~7時)運行一般的統計操作,對實時性要求都不會太高(5~10分鐘以上,甚至一天,一周等),這種數據不應在每次訪問時運行庫中直接count,group,而是應該由定時任務導出,建立結果表或中間結果表,供最終用戶使用。
◆生產數據庫上的操作權限應嚴格控制,而開發人員在生產數據庫上直接運行SQL語句,要盡量慎重。
能做到以上這些,基本上可以算MySQL以及相關系統優化入門,可以保證不要讓我們的數據庫整天累趴下了。
最后,即使做足了功課,也還是要例行的對數據庫運行情況進行觀察,監控,盡早發現其性能瓶頸,在未造成危害前解決掉。
【編輯推薦】