如何不讓一個慢查詢把服務器搞冒煙

喂?xxx嗎?大家的服務怎麼回事,機器又掛掉啦~!
啊?掛掉幾臺了?
大家借的40臺掛了兩臺啦!
騷等,我看看咋回事!mysql

服務器又冒煙了~~~緣由是這樣的:sql

前段時間項目迎來七夕高峯,有一個接口的SQL原本長這樣:數據庫

mysql> explain SELECT *,sum(num) AS sum FROM search WHERE search_time >= '2016-08-30' AND type = 0 AND state = 1 GROUP BY keyword ORDER BY sum DESC LIMIT 50;
+----+-------------+-----------+------+--------------------------+------+---------+-------+--------+----------------------------------------------+
| id | select_type | table     | type | possible_keys            | key  | key_len | ref   | rows   | Extra                                        |
+----+-------------+-----------+------+--------------------------+------+---------+-------+--------+----------------------------------------------+
|  1 | SIMPLE      | search | ref  | type,search_time,keyword | type | 2       | const | 651114 | Using where; Using temporary; Using filesort |
+----+-------------+-----------+------+--------------------------+------+---------+-------+--------+----------------------------------------------+

search_time,type,state都建了索引,typestate取值範圍有限,因此基本沒啥用,主要是靠search_time,可是explain的結果表示並無用到有效索引,實際狀況下表裏有130w+數據的時候這個語句跑起來平均耗時5s多,這確定是不能忍受的。緩存

那強制索引怎麼樣?試試看:服務器

mysql> explain SELECT *,sum(num) AS sum FROM search FORCE INDEX (search_time) WHERE search_time >= '2016-08-30' AND type = 0 AND state = 1 GROUP BY keyword ORDER BY sum DESC LIMIT 50;
+----+-------------+-----------+-------+---------------------+-------------+---------+------+--------+---------------------------------------------------------------------+
| id | select_type | table     | type  | possible_keys       | key         | key_len | ref  | rows   | Extra                                                               |
+----+-------------+-----------+-------+---------------------+-------------+---------+------+--------+---------------------------------------------------------------------+
|  1 | SIMPLE      | search | range | search_time,keyword | search_time | 4       | NULL | 290616 | Using index condition; Using where; Using temporary; Using filesort |
+----+-------------+-----------+-------+---------------------+-------------+---------+------+--------+---------------------------------------------------------------------+

有效果,rows降到29w,照理說在29w裏面怎麼查都不會太慢,可是都知道explain裏的rows只是個參考,實際跑起來仍是花了3s多,也是不能忍受的。併發

這臺數據庫的機器同時還跑其餘業務,都是量級較大的,服務器負載原本就不低,七夕還沒到,就由於這條sql把服務器搞的直冒煙,本業務慢查詢也拖慢了其餘業務的執行時間致使連鎖反應。高併發

以前已經對數據的讀取部分加了緩存,可是日誌記錄仍是顯示某段時間內產生大量的慢查詢請求。開始咱們懷疑是緩存失效,但後來發現,實際上是高併發致使在設置緩存階段,因爲sql語句執行時間太長,致使在這5秒內形成大量數據庫慢查詢。日誌

直接說解決方案吧:code

  1. 縮小查詢範圍,由以前的查詢3天改成查詢1天,量級降到130w+數據。blog

  2. 強制使用索引,必定程度上縮短查詢時間。

  3. 寫個腳本,定時將查詢結果保存到memcache裏,這個主要是防止高併發狀況下,等待寫入mc時形成短期大量數據庫訪問。

  4. 對數據庫讀取結果作緩存。

  5. 對接口結果作緩存。

作了這5步工做,媽媽不再用擔憂個人服務器會冒煙啦~~

注:後面會慢慢把其餘blog移到這裏來,之後主要在這寫啦。

相關文章
相關標籤/搜索