Mysql如何定位慢查詢,以及SQL語句執(zhí)行很慢, 如何分析呢?
思考:在MySQL中,如何定位慢查詢??
慢查詢表象:頁面加載過慢、接口壓測響應(yīng)時間過長(超過1s)
1. 方案一:開源工具
調(diào)試工具:Arthas 運維工具:Prometheus 、Skywalking
2.方案二:MySQL自帶慢日志(重點)
慢查詢?nèi)罩居涗浟怂袌?zhí)行時間超過指定參數(shù)(long_query_time,單位:秒,默認10秒)的所有SQL語句的日志。
MySQL的慢查詢?nèi)罩灸J沒有開啟,可以通過查看系統(tǒng)變量 slow_query_log。
show variables like '%slow_query_log%'
如果要開啟慢查詢?nèi)罩荆枰贛ySQL的配置文件(/etc/my.cnf)中配置如下信息
2.1. 開啟SQL慢查詢?nèi)罩?/span>
開啟SQL慢查詢?nèi)罩?,需要在MySQL的配置文件(/etc/my.cnf)中配置如下信息:
# 開啟MySQL慢日志查詢開關(guān)
slow_query_log=1
# 設(shè)置慢日志的時間為2秒,SQL語句執(zhí)行時間超過2秒,就會視為慢查詢,記錄慢查詢?nèi)罩?long_query_time=2
配置完畢之后,通過一下命令查看,日志文件地址
show variables like '%slow_query_log%';
配置完畢之后,通過以下指令重新啟動MySQL服務(wù)器進行測試,查看慢日志文件中記錄的信息
2.2. 慢查詢?nèi)绾味ㄎ豢偨Y(jié)
- 介紹一下當(dāng)時產(chǎn)生問題的場景(我們當(dāng)時的一個接口測試的時候非常的慢,壓測的結(jié)果大概5秒鐘)
- 我們系統(tǒng)中當(dāng)時采用了運維工具( Skywalking ),可以監(jiān)測出哪個接口,最終因為是sql的問題
- 在mysql中開啟了慢日志查詢,我們設(shè)置的值就是2秒,一旦sql執(zhí)行超過2秒就會記錄到日志中(調(diào)試階段)
3. explain執(zhí)行計劃
思考:那這個SQL語句執(zhí)行很慢, 如何分析呢?
可以采用EXPLAIN 或者 DESC命令獲取 MySQL 如何執(zhí)行 SELECT 語句的信息
語法:
-- 直接在select語句之前加上關(guān)鍵字 explain / desc
EXPLAIN SELECT 字段列表 FROM 表名 WHERE 條件 ;
Explain 執(zhí)行計劃中各個字段的含義:
字段 | 含義 |
id | 表示執(zhí)行順序,id相同從上到下執(zhí)行,不同值越大越先執(zhí)行 |
select_type | 示 SELECT 的類型,常見的取值有 SIMPLE(簡單表,即不使用表連接或者子查詢)、PRIMARY(主查詢,即外層的查詢)、UNION(UNION 中的第二個或者后面的查詢語句)、SUBQUERY(SELECT/WHERE之后包含了子查詢)等 |
type | 表示連接類型,性能由好到差的連接類型為NULL、system、const、eq_ref、ref、range、 index、all |
possible_key | 顯示可能應(yīng)用在這張表上的索引,一個或多個。 |
key | 實際使用的索引,如果為NULL,則沒有使用索引。 |
key_len | 索引占用的大小 |
Extra | 額外的優(yōu)化建議 |
通過它們keykey_len 和查看是否可能會命中索引
Extra | 含義 |
Using where; Using Index | 查找使用了索引,需要的數(shù)據(jù)都在索引列中能找到,不需要回表查詢數(shù)據(jù) |
Using index condition | 查找使用了索引,但是需要回表查詢數(shù)據(jù) |
3.1 type連接類型說明
- system:一般查詢系統(tǒng)中的表才會出現(xiàn)
- const:根據(jù)主鍵查詢
-- 語句中id表示的是主鍵
explain select * from tb_user where id=1;
- eq_ref:表示使用唯一索引或主鍵進行等值連接檢索。通常出現(xiàn)在具有關(guān)聯(lián)表的等值連接查詢,其中連接條件使用了唯一索引或主鍵。例如,通過外鍵連接兩個表,或者使用JOIN語句時,連接條件涉及到唯一索引或主鍵。
- ref:表示使用非唯一索引進行等值連接檢索。通常出現(xiàn)在使用非唯一索引進行查詢的情況,其中每個索引鍵值可能匹配多行記錄。
-- name 是索引
explain SELECT * FROM tb_user WHERE name= '李四';
- range::表示使用索引進行范圍查詢。通常出現(xiàn)在使用范圍操作符(如BETWEEN、>、<)進行查詢時
explain SELECT * FROM tb_user WHERE id BETWEEN 1 AND 10;
- index:示全索引掃描,即遍歷整個索引來定位記錄,而不是根據(jù)索引中的具體值進行查找。通常出現(xiàn)在沒有合適的索引可用,或者查詢需要遍歷大部分或全部索引的情況。
- all:表示全表掃描,表示沒有使用索引,需要對整個表進行遍歷來找到匹配條件的記錄。通常出現(xiàn)在沒有適用的索引、謂詞或查詢涉及表的大部分或全部數(shù)據(jù)的情況。
explain SELECT * FROM tb_user;
4. Mysql慢查詢定位面試題
面試官:MySQL中,如何定位慢查詢?
候選人:
我們當(dāng)時做壓測的時候有的接口非常的慢,接口的響應(yīng)時間超過了2秒以上,因為我們當(dāng)時的系統(tǒng)部署了運維的監(jiān)控系統(tǒng)Skywalking ,在展示的報表中可以看到是哪一個接口比較慢,并且可以分析這個接口哪部分比較慢,這里可以看到SQL的具體的執(zhí)行時間,所以可以定位是哪個sql出了問題。
如果,項目中沒有這種運維的監(jiān)控系統(tǒng),其實在MySQL中也提供了慢日志查詢的功能,可以在MySQL的系統(tǒng)配置文件中開啟這個慢日志的功能,并且也可以設(shè)置SQL執(zhí)行超過多少時間來記錄到一個日志文件中,我記得上一個項目配置的是2秒,只要SQL執(zhí)行的時間超過了2秒就會記錄到日志文件中,我們就可以在日志文件找到執(zhí)行比較慢的SQL了。
面試官:那這個SQL語句執(zhí)行很慢, 如何分析呢?
候選人:
如果一條sql執(zhí)行很慢的話,我們通常會使用mysql自動的執(zhí)行計劃explain來去查看這條sql的執(zhí)行情況,比如在這里面可以通過key和key_len檢查是否命中了索引,如果本身已經(jīng)添加了索引,也可以判斷索引是否有失效的情況,第二個,可以通過type字段查看sql是否有進一步的優(yōu)化空間,是否存在全索引掃描或全盤掃描,第三個可以通過extra建議來判斷,是否出現(xiàn)了回表的情況,如果出現(xiàn)了,可以嘗試添加索引或修改返回字段來修復(fù)