最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL慢查詢(xún)?nèi)罩鹃_(kāi)啟與使用:找到那些偷偷變慢的SQL

 更新時(shí)間:2026年06月24日 09:12:01   作者:花生了什么事o  
本文旨在幫助數(shù)據(jù)庫(kù)入門(mén)學(xué)習(xí)者掌握 MySQL 慢查詢(xún)?nèi)罩镜氖褂梅椒?從開(kāi)啟配置、日志字段解讀、mysqldumpslow工具使用,到配合 EXPLAIN 做深度分析,帶你建立一套完整的慢 SQL 排查鏈路

慢查詢(xún)?nèi)罩臼鞘裁?/h2>

慢查詢(xún)?nèi)罩臼?MySQL 提供的一個(gè)功能,它會(huì)把執(zhí)行時(shí)間超過(guò)指定閾值的 SQL 語(yǔ)句記錄到文件里。

有了慢查詢(xún)?nèi)罩?,你就不用一行一行翻代碼去猜哪條 SQL查詢(xún)較慢可能存在問(wèn)題,直接看日志就可以找到問(wèn)題SQL。

MySQL 默認(rèn)是關(guān)閉慢查詢(xún)?nèi)罩镜?,因?yàn)橛涗浫罩颈旧碛行阅荛_(kāi)銷(xiāo),所以生產(chǎn)環(huán)境通常只在排查問(wèn)題時(shí)臨時(shí)開(kāi)啟,或者設(shè)置一個(gè)相對(duì)嚴(yán)格的閾值(比如 1 秒),只記錄真正有問(wèn)題的 SQL。

開(kāi)啟慢查詢(xún)?nèi)罩?/h2>

查看當(dāng)前狀態(tài)

-- 查看慢查詢(xún)?nèi)罩臼欠耖_(kāi)啟
SHOW VARIABLES LIKE 'slow_query_log';

-- 查看閾值(單位:秒)
SHOW VARIABLES LIKE 'long_query_time';

-- 查看日志文件路徑
SHOW VARIABLES LIKE 'slow_query_log_file';

正常情況下,slow_query_log 的值是 OFF,long_query_time 默認(rèn)是 10 秒。10 秒太寬松了,生產(chǎn)環(huán)境一般設(shè)成 1 秒甚至 0.5 秒,主要還是取決于業(yè)務(wù)場(chǎng)景。

臨時(shí)開(kāi)啟(當(dāng)前會(huì)話(huà)生效)

-- 開(kāi)啟慢查詢(xún)?nèi)罩?
SET GLOBAL slow_query_log = 'ON';

-- 設(shè)置閾值為 1 秒(超過(guò) 1 秒的 SQL 才記錄)
SET GLOBAL long_query_time = 1;

-- 可選:記錄沒(méi)有使用索引的 SQL
SET GLOBAL log_queries_not_using_indexes = 'ON';

SET GLOBAL 設(shè)置的參數(shù)在 MySQL 重啟后會(huì)失效,下次啟動(dòng)還是用配置文件里的值。

永久開(kāi)啟(修改配置文件)

編輯 MySQL 的配置文件 my.cnf(Linux)或 my.ini(Windows),在 [mysqld] 段落下添加:

[mysqld]
# 開(kāi)啟慢查詢(xún)?nèi)罩?
slow_query_log = 1

# 慢查詢(xún)閾值:1 秒
long_query_time = 1

# 日志文件路徑(可以自定義)
slow_query_log_file = /var/log/mysql/slow.log

# 可選:記錄沒(méi)有使用索引的 SQL
log_queries_not_using_indexes = 1

修改之后重啟 MySQL,或者執(zhí)行 SET GLOBAL 命令讓配置立即生效。

一個(gè)小技巧log_queries_not_using_indexes 這個(gè)參數(shù)很實(shí)用。它會(huì)把所有沒(méi)走索引的 SQL 都記錄下來(lái),不管執(zhí)行時(shí)間多長(zhǎng)。這類(lèi) SQL 在數(shù)據(jù)量小的時(shí)候可能跑得很快,但隨著數(shù)據(jù)增長(zhǎng)會(huì)越來(lái)越慢,屬于"定時(shí)炸彈",有了這個(gè)功能就可以早點(diǎn)發(fā)現(xiàn)早點(diǎn)處理。

慢查詢(xún)?nèi)罩鹃L(zhǎng)什么樣

開(kāi)啟之后,我們來(lái)制造一條慢查詢(xún),看看日志長(zhǎng)什么樣。

先準(zhǔn)備一張測(cè)試表和一些數(shù)據(jù):

CREATE TABLE user_order (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    user_id BIGINT NOT NULL,
    order_no VARCHAR(32) NOT NULL,
    amount DECIMAL(10, 2),
    status VARCHAR(20),
    create_time DATETIME,
    INDEX idx_user_id (user_id)
) ENGINE=InnoDB;

-- 插入 100 萬(wàn)條測(cè)試數(shù)據(jù)
DELIMITER //
CREATE PROCEDURE generate_orders(IN n INT)
BEGIN
    DECLARE i INT DEFAULT 0;
    WHILE i < n DO
        INSERT INTO user_order (user_id, order_no, amount, status, create_time)
        VALUES (
            FLOOR(RAND() * 10000),
            CONCAT('ORD', LPAD(i, 10, '0')),
            ROUND(RAND() * 1000, 2),
            ELT(FLOOR(RAND() * 3) + 1, 'pending', 'paid', 'cancelled'),
            DATE_SUB(NOW(), INTERVAL FLOOR(RAND() * 365) DAY)
        );
        SET i = i + 1;
    END WHILE;
END //
DELIMITER ;

CALL generate_orders(1000000);

現(xiàn)在執(zhí)行一條故意不走索引的查詢(xún):

-- 對(duì) status 做模糊查詢(xún),status 上沒(méi)有索引
SELECT * FROM user_order WHERE status LIKE 'p%' ORDER BY create_time DESC LIMIT 50;

等它跑完(可能要幾秒),然后去日志文件里找找看。日志文件的路徑可以用 SHOW VARIABLES LIKE 'slow_query_log_file' 查看。

一條典型的慢查詢(xún)?nèi)罩鹃L(zhǎng)這樣:

# Time: 2026-06-21T14:32:05.123456+08:00
# User@Host: root[root] @ localhost []  Id:    42
# Query_time: 2.356789  Lock_time: 0.000123 Rows_sent: 50  Rows_examined: 1000000
SET timestamp=1718946725;
SELECT * FROM user_order WHERE status LIKE 'p%' ORDER BY create_time DESC LIMIT 50;

逐行解讀:

字段含義重點(diǎn)關(guān)注
TimeSQL 執(zhí)行的時(shí)間點(diǎn)定位問(wèn)題發(fā)生的時(shí)刻
User@Host執(zhí)行 SQL 的用戶(hù)和來(lái)源排查是不是某個(gè)服務(wù)在搞事
Query_timeSQL 執(zhí)行總耗時(shí)(秒)核心指標(biāo),越小越好
Lock_time等待鎖的時(shí)間(秒)如果很大,說(shuō)明有鎖競(jìng)爭(zhēng)
Rows_sent返回給客戶(hù)端的行數(shù)和 LIMIT 對(duì)比,看有沒(méi)有多返回
Rows_examined掃描的行數(shù)核心指標(biāo),越大說(shuō)明越低效
SQL 語(yǔ)句實(shí)際執(zhí)行的 SQL拿去 EXPLAIN 分析

最該關(guān)注的兩個(gè)數(shù)字:Query_time 和 Rows_examined。

Query_time 告訴你這條 SQL 到底慢不慢,Rows_examined 告訴你它為什么慢。如果 Rows_examined 是 100 萬(wàn),但 Rows_sent 只有 50,說(shuō)明 MySQL 掃了 100 萬(wàn)行才挑出 50 條——這就是典型的索引缺失或索引失效。

mysqldumpslow:日志分析工具

日志文件看幾條還行,但如果慢查詢(xún)很多,一條條翻就太低效了。MySQL 自帶了一個(gè)日志分析工具 mysqldumpslow,可以幫我們做匯總統(tǒng)計(jì)。

# 按執(zhí)行時(shí)間排序,取前 10 條最慢的
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log

# 按掃描行數(shù)排序,取前 10 條
mysqldumpslow -s r -t 10 /var/log/mysql/slow.log

# 按執(zhí)行次數(shù)排序,取前 10 條
mysqldumpslow -s c -t 10 /var/log/mysql/slow.log

參數(shù)說(shuō)明:

參數(shù)含義
-s t按總執(zhí)行時(shí)間排序(默認(rèn))
-s r按掃描總行數(shù)排序
-s c按執(zhí)行次數(shù)排序
-s l按鎖等待時(shí)間排序
-t N只顯示前 N 條
-g "pattern"只匹配包含指定字符串的 SQL

輸出結(jié)果類(lèi)似:

Count: 125  Time=2.36s (295s)  Lock=0.00s (0.15s)  Rows=50.0 (6250), root[root]@localhost
  SELECT * FROM user_order WHERE status LIKE 'S' ORDER BY create_time DESC LIMIT N

這一行告訴我們:這條 SQL 在統(tǒng)計(jì)時(shí)段內(nèi)執(zhí)行了 125 次,平均耗時(shí) 2.36 秒,累計(jì)耗時(shí) 295 秒,平均掃描行數(shù) 6250 條。

Count 大的說(shuō)明是高頻 SQL,Time 大的說(shuō)明是耗時(shí)大戶(hù)。 如果一條 SQL Count 和 Time 都大,那它就是性能優(yōu)化的第一優(yōu)先級(jí)。

配合 EXPLAIN 做深度分析

慢查詢(xún)?nèi)罩編湍阏业搅?quot;嫌疑人",但要定罪還需要充分的證據(jù)。所以在拿到日志里的 SQL 后,我們繼續(xù)用 EXPLAIN 看看它的執(zhí)行計(jì)劃:

EXPLAIN SELECT * FROM user_order WHERE status LIKE 'p%' ORDER BY create_time DESC LIMIT 50;

輸出可能是:

+----+------+-------+------+---------+------+----------+-----------------------------+
| id | type | key   | ref  | rows    | filtered | Extra                              |
+----+------+-------+------+---------+----------+------------------------------------+
|  1 | ALL  | NULL  | NULL | 1000000 |    33.33 | Using where; Using filesort        |
+----+------+-------+------+---------+----------+------------------------------------+

四個(gè)危險(xiǎn)信號(hào):

  1. type = ALL:全表掃描,沒(méi)走索引
  2. key = NULL:沒(méi)有可用索引
  3. rows = 1000000:掃描了 100 萬(wàn)行
  4. Extra = Using filesort:額外排序

和日志里的 Rows_examined = 1000000 對(duì)上了。問(wèn)題很明確:status 列沒(méi)有索引,MySQL 只能全表掃描。

優(yōu)化方案:給 status 加索引,或者改成聯(lián)合索引 (status, create_time) 同時(shí)覆蓋過(guò)濾和排序:

ALTER TABLE user_order ADD INDEX idx_status_time (status, create_time);

再查一次 EXPLAIN:

+----+-------+----------------+------+---------+------+----------+-------+
| id | type  | key            | ref  | rows    | filtered | Extra       |
+----+-------+----------------+------+---------+----------+-------------+
|  1 | range | idx_status_time| NULL |  333333 |   100.00 | Using where |
+----+-------+----------------+------+---------+----------+-------------+

type 從 ALL 變成了 range,rows 從 100 萬(wàn)降到了 33 萬(wàn),Using filesort 也沒(méi)了。執(zhí)行時(shí)間從 2 秒多降到幾百毫秒。

慢查詢(xún)?nèi)罩矩?fù)責(zé)"發(fā)現(xiàn)問(wèn)題",EXPLAIN 負(fù)責(zé)"定位原因",兩者配合才是完整的調(diào)優(yōu)鏈路。

常見(jiàn)問(wèn)題排查清單

拿到慢查詢(xún)?nèi)罩竞?,按照這個(gè)清單逐項(xiàng)檢查:

現(xiàn)象可能原因排查方法
Rows_examined 遠(yuǎn)大于 Rows_sent索引缺失或索引失效EXPLAIN 看 type 和 key
Query_time 大但 Rows_examined 不大鎖等待、IO 等待關(guān)注 Lock_time,檢查是否有表鎖
同一條 SQL 時(shí)快時(shí)慢執(zhí)行計(jì)劃不穩(wěn)定EXPLAIN 看是否有多個(gè)候選索引
日志里出現(xiàn)大量相同 SQL慢查詢(xún)集中在某幾張表mysqldumpslow -s c 統(tǒng)計(jì)頻次
某個(gè)時(shí)間段集中出現(xiàn)慢查詢(xún)定時(shí)任務(wù)、批量導(dǎo)入檢查 Time 字段的時(shí)間分布
Lock_time 很大有事務(wù)長(zhǎng)時(shí)間未提交檢查 SHOW ENGINE INNODB STATUS

一個(gè)實(shí)用的排查流程:

小結(jié)

慢查詢(xún)?nèi)罩臼?MySQL 性能排查的起點(diǎn)。它幫你從海量 SQL 中篩選出真正有問(wèn)題的那些,附上執(zhí)行時(shí)間、掃描行數(shù)等關(guān)鍵指標(biāo),讓你的調(diào)優(yōu)工作有的放矢。

從實(shí)際操作來(lái)看,慢查詢(xún)?nèi)罩?+ EXPLAIN 是一對(duì)黃金搭檔。前者負(fù)責(zé)"發(fā)現(xiàn)",后者負(fù)責(zé)"診斷"。發(fā)現(xiàn)問(wèn)題是第一步,解決問(wèn)題是第二步,在后端面試之中遇到“mysql如何調(diào)優(yōu)”這個(gè)問(wèn)題,我們就可以采用這個(gè)思路進(jìn)行回答。在實(shí)際工作生產(chǎn)環(huán)境中,我們依然使用這個(gè)思路進(jìn)行實(shí)際的排查優(yōu)化。

以上就是MySQL慢查詢(xún)?nèi)罩鹃_(kāi)啟與使用:找到那些偷偷變慢的SQL的詳細(xì)內(nèi)容,更多關(guān)于MySQL慢查詢(xún)?nèi)罩镜馁Y料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MySQL遷移KingbaseESV8R2的實(shí)現(xiàn)步驟

    MySQL遷移KingbaseESV8R2的實(shí)現(xiàn)步驟

    本文主要介紹了MySQL遷移KingbaseESV8R2的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • mysql 8.0.11安裝配置方法圖文教程

    mysql 8.0.11安裝配置方法圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 8.0.11安裝配置方法圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • DBeaver連接mysql數(shù)據(jù)庫(kù)圖文教程(超詳細(xì))

    DBeaver連接mysql數(shù)據(jù)庫(kù)圖文教程(超詳細(xì))

    本文主要介紹了DBeaver連接mysql數(shù)據(jù)庫(kù)圖文教程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Centos7 下Mysql5.7.19安裝教程詳解

    Centos7 下Mysql5.7.19安裝教程詳解

    這篇文章主要介紹了Centos7 下Mysql5.7.19安裝教程詳解,小編認(rèn)為非常不錯(cuò),特此分享到腳本之家平臺(tái),需要的朋友參考下吧
    2017-09-09
  • SQL調(diào)優(yōu)實(shí)戰(zhàn)之讓查詢(xún)效率飆升10倍的實(shí)用技巧

    SQL調(diào)優(yōu)實(shí)戰(zhàn)之讓查詢(xún)效率飆升10倍的實(shí)用技巧

    在數(shù)據(jù)洪流時(shí)代,企業(yè)每1毫秒的查詢(xún)延遲都可能造成百萬(wàn)級(jí)營(yíng)收損失,本文將結(jié)合18個(gè)真實(shí)案例與28段代碼示例,揭示從索引設(shè)計(jì)到執(zhí)行計(jì)劃分析的完整優(yōu)化鏈路,助你掌握讓查詢(xún)效率提升10倍的核心方法,實(shí)現(xiàn)降本增效的技術(shù)躍遷
    2026-01-01
  • MySQL中使用SQL語(yǔ)句查看某個(gè)表的編碼方法

    MySQL中使用SQL語(yǔ)句查看某個(gè)表的編碼方法

    下面小編就為大家?guī)?lái)一篇MySQL中使用SQL語(yǔ)句查看某個(gè)表的編碼方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2016-11-11
  • 一文深入探究MySQL自增鎖

    一文深入探究MySQL自增鎖

    MySQL的自增鎖是指在使用自增主鍵(Auto?Increment)時(shí),為了保證唯一性和正確性,系統(tǒng)會(huì)對(duì)自增字段進(jìn)行加鎖,這樣可以確保同時(shí)插入多條記錄時(shí),每條記錄都能夠獲得唯一的自增值,本將和大家一起深入探究MySQL自增鎖,需要的朋友可以參考下
    2023-08-08
  • MySQL如何比較時(shí)間(datetime)大小

    MySQL如何比較時(shí)間(datetime)大小

    這篇文章主要介紹了MySQL如何比較時(shí)間(datetime)大小,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • mysql查詢(xún)當(dāng)天的數(shù)據(jù)

    mysql查詢(xún)當(dāng)天的數(shù)據(jù)

    這篇文章主要介紹了mysql查詢(xún)當(dāng)天的數(shù)據(jù),第一種數(shù)量小的時(shí)候用,數(shù)據(jù)量稍微起來(lái)巨慢,第二種速度快,但是最好配合復(fù)合索引來(lái)查,避免全表掃描,需要的朋友可以參考下
    2023-08-08
  • mysql 8.0.16 Win10 zip版本安裝配置圖文教程

    mysql 8.0.16 Win10 zip版本安裝配置圖文教程

    這篇文章主要為大家詳細(xì)介紹了mysql 8.0 Win10 zip版本安裝配置圖文教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-06-06

最新評(píng)論

南丰县| 九龙城区| 兴义市| 东宁县| 拜城县| 清水县| 兴化市| 哈尔滨市| 洞口县| 保靖县| 察隅县| 灵川县| 抚州市| 彭水| 芜湖市| 安西县| 太保市| 南和县| 屯昌县| 集贤县| 伽师县| 巴彦淖尔市| 和平区| 綦江县| 新晃| 廉江市| 循化| 固原市| 教育| 太白县| 阳山县| 息烽县| 如东县| 中西区| 新竹县| 赫章县| 曲靖市| 萍乡市| 邵武市| 甘谷县| 大关县|