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

MySQL慢查詢優(yōu)化從30秒到300毫秒的完整過程

 更新時(shí)間:2025年12月09日 09:09:16   作者:嘻哈baby  
文章介紹了如何優(yōu)化一個(gè)響應(yīng)時(shí)間為30秒的SQL接口,將響應(yīng)時(shí)間優(yōu)化到300毫秒的過程,通過開啟慢查詢?nèi)罩尽⒎治鯯QL執(zhí)行計(jì)劃、添加聯(lián)合索引和優(yōu)化查詢技巧等步驟,解決了慢查詢問題,文章還分享了索引設(shè)計(jì)原則、實(shí)用工具和遠(yuǎn)程數(shù)據(jù)庫(kù)排查技巧,需要的朋友可以參考下

最近接手一個(gè)老項(xiàng)目,某個(gè)列表接口響應(yīng)時(shí)間30秒,用戶瘋狂投訴。

排查下來是SQL問題,優(yōu)化后降到300毫秒。記錄一下完整過程。

一、發(fā)現(xiàn)問題

1.1 開啟慢查詢?nèi)罩?/h3>
-- 查看是否開啟
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';

-- 開啟慢查詢?nèi)罩?
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;  -- 超過1秒記錄
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';

1.2 分析慢查詢?nèi)罩?/h3>
# 用mysqldumpslow分析
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log

# 輸出
Count: 1532  Time=28.35s (43424s)  Lock=0.00s (0s)  Rows=100.0 (153200)
  SELECT * FROM orders WHERE user_id = N AND status = N ORDER BY create_time DESC LIMIT N, N

找到了!這條SQL執(zhí)行了1532次,平均28秒。

二、分析SQL

2.1 問題SQL

SELECT * 
FROM orders 
WHERE user_id = 12345 
  AND status = 1 
ORDER BY create_time DESC 
LIMIT 0, 20;

看起來很簡(jiǎn)單,為什么慢?

2.2 EXPLAIN分析

EXPLAIN SELECT * FROM orders WHERE user_id = 12345 AND status = 1 ORDER BY create_time DESC LIMIT 0, 20;
+----+-------------+--------+------+---------------+------+---------+------+----------+-----------------------------+
| id | select_type | table  | type | possible_keys | key  | key_len | rows | filtered | Extra                       |
+----+-------------+--------+------+---------------+------+---------+------+----------+-----------------------------+
|  1 | SIMPLE      | orders | ALL  | NULL          | NULL | NULL    | 5000000 | 0.10  | Using where; Using filesort |
+----+-------------+--------+------+---------------+------+---------+------+----------+-----------------------------+

問題暴露了:

  • type = ALL:全表掃描
  • key = NULL:沒用到索引
  • rows = 5000000:掃描500萬行
  • Using filesort:額外排序

2.3 查看表結(jié)構(gòu)

SHOW CREATE TABLE orders;
CREATE TABLE `orders` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `user_id` bigint NOT NULL,
  `status` tinyint NOT NULL DEFAULT '0',
  `amount` decimal(10,2) NOT NULL,
  `create_time` datetime NOT NULL,
  `update_time` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

果然,只有主鍵索引,沒有業(yè)務(wù)索引。

三、優(yōu)化方案

3.1 添加聯(lián)合索引

-- 創(chuàng)建聯(lián)合索引
ALTER TABLE orders ADD INDEX idx_user_status_time (user_id, status, create_time);

再次EXPLAIN:

+----+-------------+--------+------+---------------------+---------------------+---------+-------------+------+-------+
| id | select_type | table  | type | possible_keys       | key                 | key_len | ref         | rows | Extra |
+----+-------------+--------+------+---------------------+---------------------+---------+-------------+------+-------+
|  1 | SIMPLE      | orders | ref  | idx_user_status_time| idx_user_status_time| 9       | const,const | 156  | NULL  |
+----+-------------+--------+------+---------------------+---------------------+---------+-------------+------+-------+

完美:

  • type = ref:使用索引
  • rows = 156:只掃描156行
  • Extra = NULL:不需要額外排序

3.2 為什么這樣設(shè)計(jì)索引?

聯(lián)合索引順序:(user_id, status, create_time)

查詢條件:WHERE user_id = ? AND status = ?
排序條件:ORDER BY create_time

索引匹配過程:
1. user_id = 12345  → 定位到用戶的訂單
2. status = 1       → 進(jìn)一步過濾狀態(tài)
3. create_time      → 索引本身有序,無需filesort

聯(lián)合索引設(shè)計(jì)原則:

  1. 等值查詢的列放前面
  2. 排序的列放最后
  3. 遵循最左前綴原則

3.3 優(yōu)化效果

優(yōu)化前:28.35秒,掃描500萬行
優(yōu)化后:0.003秒,掃描156行

提升:9000倍+

四、更多優(yōu)化技巧

4.1 避免SELECT *

-- 差:查詢所有字段
SELECT * FROM orders WHERE ...

-- 好:只查需要的字段
SELECT id, user_id, amount, create_time FROM orders WHERE ...

好處:

  • 減少網(wǎng)絡(luò)傳輸
  • 可能用到覆蓋索引

4.2 覆蓋索引

如果查詢的字段都在索引里,不需要回表:

-- 索引:idx_user_status_time (user_id, status, create_time)

-- 這個(gè)查詢可以用覆蓋索引
SELECT user_id, status, create_time FROM orders WHERE user_id = 12345;

-- EXPLAIN顯示 Using index

4.3 避免索引失效

-- ? 對(duì)索引列使用函數(shù)
SELECT * FROM orders WHERE DATE(create_time) = '2024-01-01';

-- ? 改寫
SELECT * FROM orders WHERE create_time >= '2024-01-01' AND create_time < '2024-01-02';

-- ? 隱式類型轉(zhuǎn)換
SELECT * FROM orders WHERE user_id = '12345';  -- user_id是bigint

-- ? 類型一致
SELECT * FROM orders WHERE user_id = 12345;

-- ? LIKE前置通配符
SELECT * FROM orders WHERE order_no LIKE '%ABC';

-- ? LIKE后置通配符(可以用索引)
SELECT * FROM orders WHERE order_no LIKE 'ABC%';

4.4 分頁(yè)優(yōu)化

-- ? 深分頁(yè)很慢
SELECT * FROM orders ORDER BY id LIMIT 1000000, 20;
-- 需要掃描100萬行

-- ? 用游標(biāo)分頁(yè)
SELECT * FROM orders WHERE id > 1000000 ORDER BY id LIMIT 20;
-- 直接定位,很快

五、索引設(shè)計(jì)原則

5.1 什么時(shí)候建索引?

場(chǎng)景是否建索引
WHERE條件頻繁查詢的列? 是
ORDER BY排序的列? 是
JOIN關(guān)聯(lián)的列? 是
區(qū)分度低的列(如性別)? 否
頻繁更新的列?? 權(quán)衡

5.2 聯(lián)合索引順序

原則:
1. 區(qū)分度高的列放前面
2. 等值查詢的列放前面
3. 排序列放最后

六、實(shí)用工具

6.1 慢查詢分析

# mysqldumpslow
mysqldumpslow -s t -t 10 slow.log  # 按時(shí)間排序,前10條

# pt-query-digest(推薦)
pt-query-digest slow.log > report.txt

6.2 EXPLAIN詳解

type(重要,從好到差):
- system/const:常量查詢
- eq_ref:主鍵/唯一索引
- ref:普通索引
- range:范圍掃描
- index:索引全掃描
- ALL:全表掃描 ?

Extra(重要):
- Using index:覆蓋索引 ?
- Using where:需要回表過濾
- Using filesort:額外排序 ??
- Using temporary:臨時(shí)表 ??

七、遠(yuǎn)程數(shù)據(jù)庫(kù)排查技巧

有時(shí)候問題數(shù)據(jù)庫(kù)在測(cè)試環(huán)境,本地連不上怎么辦?

我的做法是用組網(wǎng)工具把本地和測(cè)試服務(wù)器連起來。之前用VPN,經(jīng)常斷還慢。現(xiàn)在用星空組網(wǎng),本地直接連測(cè)試環(huán)境的MySQL:

# 組網(wǎng)后直接用虛擬IP連接
mysql -h 192.168.188.10 -u root -p

EXPLAIN、慢查詢分析都能直接在本地跑,比登服務(wù)器方便多了。

總結(jié)

SQL優(yōu)化核心步驟:

1. 開啟慢查詢?nèi)罩?→ 發(fā)現(xiàn)問題SQL
2. EXPLAIN分析 → 定位問題原因
3. 添加/優(yōu)化索引 → 解決問題
4. 再次EXPLAIN → 驗(yàn)證效果
5. 線上執(zhí)行 → 監(jiān)控觀察

記住幾個(gè)原則:

  • 避免全表掃描
  • 利用覆蓋索引
  • 注意索引失效場(chǎng)景
  • 聯(lián)合索引最左前綴

以上就是MySQL慢查詢優(yōu)化從30秒到300毫秒的完整過程的詳細(xì)內(nèi)容,更多關(guān)于MySQL慢查詢優(yōu)化30秒到300毫秒的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解 MySQL中count函數(shù)的正確使用方法

    詳解 MySQL中count函數(shù)的正確使用方法

    這篇文章主要介紹了 MySQL中count函數(shù)的正確使用方法,幫助大家更好的理解和使用MySQL數(shù)據(jù)庫(kù),感興趣的朋友可以了解下。
    2020-11-11
  • 一文帶你深入了解?MySQL的鎖機(jī)制

    一文帶你深入了解?MySQL的鎖機(jī)制

    在數(shù)據(jù)庫(kù)系統(tǒng)中,同時(shí)有多個(gè)用戶或進(jìn)程訪問數(shù)據(jù)是常見的情況,為了確保數(shù)據(jù)的完整性和一致性,數(shù)據(jù)庫(kù)管理系統(tǒng)引入了鎖機(jī)制,本文將深入探討?MySQL?鎖機(jī)制,幫助您理解鎖的分類、實(shí)現(xiàn)方式以及使用場(chǎng)景和優(yōu)化策略,需要的朋友可以參考下
    2023-05-05
  • MySQL刪除了記錄不生效的原因排查

    MySQL刪除了記錄不生效的原因排查

    這篇文章主要介紹了MySQL刪除了記錄不生效的原因排查,幫助大家解決MySQL刪除語句不生效的問題,感興趣的朋友可以了解下
    2020-11-11
  • MySQL阻塞與死鎖的解決

    MySQL阻塞與死鎖的解決

    本文主要介紹了MySQL阻塞與死鎖的解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • 詳解MySQL的sql_mode查詢與設(shè)置

    詳解MySQL的sql_mode查詢與設(shè)置

    這篇文章主要介紹了詳解MySQL的sql_mode查詢與設(shè)置,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Centos 7 安裝mysql5.7.24二進(jìn)制 版本的方法及解決辦法

    Centos 7 安裝mysql5.7.24二進(jìn)制 版本的方法及解決辦法

    這篇文章主要介紹了Centos 7 安裝mysql5.7.24二進(jìn)制 版本的方法 及遇到問題解決辦法,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2018-11-11
  • 一文詳解小白也能懂的SQL高效去重技巧

    一文詳解小白也能懂的SQL高效去重技巧

    當(dāng)你的數(shù)據(jù)中有重復(fù)記錄時(shí),如何快速找到每個(gè)分組的最新一條,一個(gè)優(yōu)雅的SQL查詢就能解決,下面小編就來和大家詳細(xì)講解一下SQL高效的去重技巧吧
    2025-07-07
  • MySQL無法啟動(dòng)、無法停止解決方法(安全設(shè)置后容易出現(xiàn))

    MySQL無法啟動(dòng)、無法停止解決方法(安全設(shè)置后容易出現(xiàn))

    最近在Win2003上的MySQL出現(xiàn)過多次正常運(yùn)行時(shí)無法連接數(shù)據(jù)庫(kù)故障,根本原因就是因?yàn)榘踩O(shè)置以后容易出現(xiàn)的問題,其實(shí)很簡(jiǎn)單的解決
    2012-03-03
  • mysql 5.7 zip archive版本安裝教程

    mysql 5.7 zip archive版本安裝教程

    這篇文章主要為大家詳細(xì)介紹了mysql 5.7 zip archive版本安裝教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • 淺析MySQL索引結(jié)構(gòu)采用B+樹的問題

    淺析MySQL索引結(jié)構(gòu)采用B+樹的問題

    數(shù)據(jù)庫(kù)的存儲(chǔ)引擎都是采用B樹或者B+樹來實(shí)現(xiàn)索引的存儲(chǔ),總體來說,我認(rèn)為技術(shù)方案的選型,更多的要根據(jù)具體的業(yè)務(wù)場(chǎng)景來決定,并不一定是說B+樹就是最好的選擇,就像MongoDB里面采用B樹結(jié)構(gòu),本文介紹我對(duì)MySQL索引結(jié)構(gòu)采用B+樹的理解
    2022-06-06

最新評(píng)論

石景山区| 莆田市| 扶风县| 金堂县| 尚义县| 贵德县| 廊坊市| 轮台县| 巴林右旗| 绍兴市| 三台县| 修文县| 荣昌县| 怀宁县| 泸溪县| 辉县市| 吉安县| 长汀县| 南木林县| 保山市| 忻州市| 介休市| 平顶山市| 盘锦市| 广州市| 张掖市| 扶绥县| 开封县| 广宗县| 凤翔县| 都江堰市| 滨州市| 阿瓦提县| 贵溪市| 古蔺县| 无棣县| 福鼎市| 柳州市| 永嘉县| 海阳市| 怀柔区|