MySQL慢查詢排查與優(yōu)化指南
開啟慢查詢?nèi)罩?→ 抓取慢 SQL → 分析 SQL 執(zhí)行計劃 → 優(yōu)化 SQL / 索引。
首先開發(fā)MySQL 慢查詢
登錄 MySQL 查看當前狀態(tài)
-- 查看慢查詢?nèi)罩菊w開關(guān) show variables like 'slow_query_log'; -- 查看慢查詢閾值(默認 10秒) show variables like 'long_query_time'; -- 查看慢日志文件存放路徑 show variables like 'slow_query_log_file';
臨時開啟(重啟失效,適合臨時排查)
-- 1. 開啟慢查詢?nèi)罩? set global slow_query_log = ON; -- 2. 設(shè)置閾值:執(zhí)行超過 1秒 就記錄 set global long_query_time = 1; -- 3. 可選:記錄沒有走索引的SQL set global log_queries_not_using_indexes = ON;
注意:global 修改后,新連接才生效,當前會話需要重連。
永久開啟(my.cnf/my.ini,生產(chǎn)推薦)
1. 找到配置文件
- Linux:
/etc/my.cnf或/etc/mysql/my.cnf - Windows:
my.ini
2. 在 [mysqld] 模塊添加
[mysqld] # 開啟慢查詢?nèi)罩? slow_query_log = 1 # 慢日志文件路徑 slow_query_log_file = /var/log/mysql/slow.log # 慢查詢時間閾值 1s long_query_time = 1 # 記錄未使用索引的SQL log_queries_not_using_indexes = 1 # 避免日志刷爆,限制每分鐘記錄條數(shù) log_throttle_queries_not_using_indexes = 10
3. 重啟 MySQL 生效
# CentOS systemctl restart mysqld # Ubuntu systemctl restart mysql
long_query_time:包含鎖等待時間,不只是 SQL 執(zhí)行時間- 慢日志會損耗少量 IO,生產(chǎn)不要開太大閾值,一般設(shè) 1s
- 大流量環(huán)境不要開啟
log_queries_not_using_indexes,容易日志爆炸
查看慢查詢?nèi)罩?/h2>
直接看日志文件
# 查看最后100行慢查詢 tail -n 100 /var/lib/mysql/localhost-slow.log
日志里會記錄:
- 執(zhí)行時間
- 鎖等待時間
- 掃描行數(shù)
- 具體 SQL 語句
mysqldumpslow(MySQL 自帶)
# 查看耗時最多的10條慢SQL mysqldumpslow -s t -t 10 /var/log/mysql/slow.log # 按訪問次數(shù)排序 mysqldumpslow -s c -t 10 慢日志路徑
專業(yè)工具
pt-query-digest(Percona 工具集,線上分析首選)- 配合監(jiān)控:Prometheus + Grafana、阿里云 / 云數(shù)據(jù)庫自帶慢查詢分析
分析慢 SQL
抓到慢 SQL 后,用 EXPLAIN 看執(zhí)行計劃,判斷問題在哪。
-- `EXPLAIN` 是 MySQL 提供的**診斷命令**, EXPLAIN SELECT * FROM orders WHERE user_id = 1001 AND create_time > '2025-01-01';
type:最重要
ALL:全表掃描(最差,必須優(yōu)化)index:索引全掃描range:范圍索引(正常)ref/eq_ref:精準索引(優(yōu)秀)
key:實際使用的索引
- 為
NULL= 沒用到索引
rows:掃描的行數(shù)
- 越大越慢
常見慢查詢原因 & 解決方案
沒有索引 / 索引失效(80% 場景): WHERE、JOIN、ORDER BY 字段沒建索引
-- 給 user_id + create_time 建【聯(lián)合索引】 CREATE INDEX idx_user_id_create_time ON orders(user_id, create_time);
索引失效的典型寫法
-- 會導(dǎo)致索引失效 不能對【索引列】做任何函數(shù)運算、四則運算、隱式轉(zhuǎn)換、后置模糊匹配 SELECT * FROM t WHERE YEAR(create_time) = 2025; SELECT * FROM t WHERE id + 1 = 100; SELECT * FROM t WHERE name LIKE '%張三';
改成:
SELECT * FROM t WHERE create_time >= '2025-01-01' AND create_time < '2026-01-01'; SELECT * FROM t WHERE id = 99; SELECT * FROM t WHERE name LIKE '張三%';
一次性查詢太多數(shù)據(jù)
SELECT * FROM big_table; -- 無WHERE條件,全表掃描
解決:加 LIMIT、分頁、分批查詢。
鎖等待 / 大事務(wù): SQL 本身很快,但執(zhí)行時間很長
-- 查看 InnoDB 底層實時狀態(tài) SHOW ENGINE INNODB STATUS;
看事務(wù)鎖等待信息。
數(shù)據(jù)庫服務(wù)器負載高: CPU/IO/內(nèi)存 瓶頸
SHOW PROCESSLIST; -- 查看正在執(zhí)行的SQL
到此這篇關(guān)于MySQL慢查詢排查與優(yōu)化指南的文章就介紹到這了,更多相關(guān)MySQL慢查詢排查與優(yōu)化內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mysql8.0?lower_case_table_names?大小寫敏感設(shè)置問題解決
在默認情況下,這個變量是設(shè)置為0的,以保持向前兼容性,如果將該變量設(shè)置為1,則表名和數(shù)據(jù)庫名將被區(qū)分大小寫,本文主要介紹了mysql8.0?lower_case_table_names?大小寫敏感設(shè)置問題解決,感興趣的可以了解一下2023-09-09
Docker安裝mysql配置大小寫不敏感掛載數(shù)據(jù)卷存儲操作步驟
這篇文章主要介紹了Docker安裝mysql配置大小寫不敏感掛載數(shù)據(jù)卷存儲操作步驟詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11
如何用mysql自帶的定時器定時執(zhí)行sql(每天0點執(zhí)行與間隔分/時執(zhí)行)
在開發(fā)過程中經(jīng)常會遇到這樣一個問題,每天或者每月必須定時去執(zhí)行一條sql語句或更新或刪除或執(zhí)行特定的sql語句,下面這篇文章主要給大家介紹了關(guān)于如何用mysql自帶的定時器定時執(zhí)行sql(每天0點執(zhí)行與間隔分/時執(zhí)行)的相關(guān)資料,需要的朋友可以參考下2023-03-03

