最近項目上遇到點問題,服務器出現鏈接超時。上次也是超時,問題定位到mongodb上,那次我修改好了,此次發現應該不是這個的問題了。java
初步懷疑是mysql這邊出問題了,寫的sql沒通過壓力測試,致使用戶量多的時候,出現擁堵。mysql
好,那就來看看mysql方便的慢查詢吧,來看看具體的哪些sql查詢慢,從這裏開始來優化下。sql
一:開啓慢查詢mongodb
先來看看慢查詢日誌設置的時間長度:數據庫
show VARIABLES LIKE 'long%'
返回,long_query_time 指定了慢查詢的閾值,即若是執行語句的時間超過該閾值則爲慢查詢語句,默認值爲10秒。這裏設置的爲1s服務器
慢查詢日誌開啓狀況:app
SHOW VARIABLES LIKE 'slow%'
返回:slow_query_log的值爲ON爲開啓慢查詢日誌,OFF則爲關閉慢查詢日誌。函數
slow_query_log_file 的值是記錄的慢查詢日誌到文件中(注意:默認名爲主機名.log,慢查詢日誌是否寫入指定文件中,須要指定慢查詢的輸出日誌格式爲文件,相關命令爲:show variables like ‘%log_output%’;去查看輸出的格式)測試
經過以上命令,肯定慢查詢已經打開了。而後去看慢查詢日誌就行。優化
因爲這裏用的是阿里雲的數據庫,因此提供了後臺能夠很方便的查詢到日誌和下載日誌。
這裏點擊下載便可將慢查詢的日誌下載下來。
二:分析慢查詢日誌
1. 截取一段慢查詢日誌:
# Time: 180918 19:06:21 # User@Host: proxy[proxy] @ [192.168.0.16] Id: 6707197 # Query_time: 1.015429 Lock_time: 0.000116 Rows_sent: 1 Rows_examined: 44438 SET timestamp=1537268781; select id, user_id, device_uuid, bd_client_id, bd_user_id, bd_tag, nodisturb_mode, nodisturb_start_time, nodisturb_end_time, binding_time, device_os_type, app_type, state from app_mobile_device where user_id = '78436' and app_type = 'YGY' order by binding_time desc; # User@Host: proxy[proxy] @ [192.168.0.16] Id: 6707236 # Query_time: 1.021662 Lock_time: 0.000083 Rows_sent: 1 Rows_examined: 44438 SET timestamp=1537268781; select id, user_id, device_uuid, bd_client_id, bd_user_id, bd_tag, nodisturb_mode, nodisturb_start_time, nodisturb_end_time, binding_time, device_os_type, app_type, state from app_mobile_device where user_id = '14433' and app_type = 'YGY' order by binding_time desc;
這裏能夠看到:
Query_time (慢查詢語句的查詢時間) 都超過了設置的 1s,
Rows_sent (慢查詢返回記錄) 這裏只返回了 1 條
Rows_examined (慢查詢掃描過的行數) 44438 -> 經過這裏大概能夠看出問題很大
2.如今將這個SQL語句放到數據庫去執行,並使用EXPLAIN分析 看下執行計劃。
EXPLAIN select id, user_id, device_uuid, bd_client_id, bd_user_id, bd_tag, nodisturb_mode, nodisturb_start_time, nodisturb_end_time, binding_time, device_os_type, app_type, state from app_mobile_device where user_id = '78436' and app_type = 'YGY' order by binding_time desc;
查詢結果是:
解釋下參數:
SELECT識別符。這是SELECT的查詢序列號 | |
select_type | SELECT類型,能夠爲如下任何一種:
|
table | 輸出的行所引用的表 |
type | 聯接類型。下面給出各類聯接類型,按照從最佳類型到最壞類型進行排序:
|
possible_keys | 指出MySQL能使用哪一個索引在該表中找到行 |
key | 顯示MySQL實際決定使用的鍵(索引)。若是沒有選擇索引,鍵是NULL。 |
key_len | 顯示MySQL決定使用的鍵長度。若是鍵是NULL,則長度爲NULL。 |
ref | 顯示使用哪一個列或常數與key一塊兒從表中選擇行。 |
rows | 顯示MySQL認爲它執行查詢時必須檢查的行數。多行之間的數據相乘能夠估算要處理的行數。 |
filtered | 顯示了經過條件過濾出的行數的百分比估計值。 |
Extra | 該列包含MySQL解決查詢的詳細信息
|
這裏能夠發現:rows 爲查詢的行數,查詢了4w多行,那慢是確定的了。
由於這裏是好幾個條件,而且沒有使用一個索引,那就只能給添加索引了,
這裏給選擇添加普通多列索引,由於這個表在最開始設計出問題了,致使有重複的數據,不能設置惟一索引了。
ALTER TABLE app_mobile_device ADD INDEX user_app_type_only ( `user_id` ,`app_type` )
索引設置了,再看下剛的SQL的執行計劃。
能夠發現rows 的檢查行數,很明顯的降低了。
到此,慢查詢的使用和優化就基本完成了。