MySQL 慢查詢定位與 SQL 性能優(yōu)化實戰(zhàn)教程
如何定位并解決慢查詢?
1. 開啟/檢查慢日志
- 看一下是否開啟慢日志
SHOW VARIABLES LIKE 'slow_query_log'; SHOW VARIABLES LIKE 'long_query_time'; SHOW VARIABLES LIKE 'slow_query_log_file';
- 如果未開啟,臨時開啟(生產(chǎn)環(huán)境建議永久配置):
SET GLOBAL slow_query_log = ON; SET GLOBAL long_query_time = 1;
2. 分析日志
mysqldumpslow(MySQL 自帶)
# 按執(zhí)行次數(shù)排序前10條 mysqldumpslow -s c -t 10 /var/log/mysql/slow.log # 按總耗時排序前10條 mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
3. 用explain分析執(zhí)行計劃
在SQL前面加explain
EXPLAIN SELECT id, order_no FROM orders WHERE user_id = 100 AND create_time >= '2024-01-01' ORDER BY create_time DESC;
- 重點查看四個字段
| 字段 | 看什么 |
|---|---|
| type | 是否出現(xiàn) ALL(全表掃描) |
| rows | 掃描行數(shù)是否過大 |
| key | 是否使用到了正確索引 |
| Extra | 是否出現(xiàn) Using filesort 或 Using temporary |
SQL優(yōu)化?
一、基礎(chǔ)優(yōu)化
1. 避免select *
-- ? 不推薦 SELECT * FROM users; -- ? 推薦 SELECT id, name, email FROM users;
2. 使用合適的where條件
- 盡量在where中使用索引字段
- 避免對字段進行函數(shù)操作或類型轉(zhuǎn)換(導致索引失效)
-- ? 索引失效 SELECT * FROM orders WHERE YEAR(create_time) = 2024; -- ? 使用范圍查詢,可走索引 SELECT * FROM orders WHERE create_time >= '2024-01-01' AND create_time < '2025-01-01';
3. 合理使用索引
- 對經(jīng)常用于where、join、order by、group by的列建立索引
- 比賣你過度索引(影響寫入性能)
- 考慮使用復合索引(最左前綴原則)
4. 避免全表掃描
通過explain檢查是否使用了索引
EXPLAIN SELECT * FROM products WHERE category_id = 10;
二、JOIN優(yōu)化(多表查詢)
1. 大表驅(qū)動小表
- 在MySQL中,通常將小結(jié)果姐放在left,大表在right
2. 確保JOIN字段都有索引
- 兩個表關(guān)聯(lián)字段都應(yīng)該有索引
3. 避免多層嵌套JOIN
- 復雜JOIN可拆分為多個簡單查詢
三、子查詢 vsJOIN
子查詢在某些數(shù)據(jù)庫中效率較低,可以嘗試改成JOIN
-- ? 子查詢(可能低效) SELECT * FROM users WHERE id IN (SELECT user_id FROM orders WHERE amount > 100); -- ? 改寫為 JOIN SELECT DISTINCT u.* FROM users u JOIN orders o ON u.id = o.user_id WHERE o.amount > 100;
分頁優(yōu)化
- 深分頁(如LIMIT 100000,20)性能查,因為要跳過大量的數(shù)據(jù)
- 優(yōu)化方案:
- 使用游標分頁(基于上一頁最后一條記錄的ID或時間):
- 優(yōu)化方案:
? SELECT * FROM messages WHERE id > 100000 ORDER BY id LIMIT 20; ?
如何創(chuàng)建、使用索引?
索引介紹
| 索引類型 | 說明 |
|---|---|
| 主鍵索引 | 聚簇索引,數(shù)據(jù)按主鍵物理存儲,每一張表只能一個 |
| 唯一索引 | 不允許出現(xiàn)重復值 |
| 普通索引 | 最基本的索引,允許重復和null |
| 全文索引 | 用于文本搜索 |
| 前綴索引 | 對字符串類的前N個字段創(chuàng)建索引,節(jié)省空間 |
| 覆蓋索引 | 非獨立類型,查詢字段全部包含在索引中,無需回表 |
一、創(chuàng)建索引
1. 創(chuàng)建普通索引
-- 方法1:CREATE INDEX(推薦用于已有表) CREATE INDEX index_name ON table_name (column_name); -- 示例:在 users 表的 email 字段上創(chuàng)建索引 CREATE INDEX idx_email ON users (email);
2. 創(chuàng)建唯一索引
CREATE UNIQUE INDEX idx_username ON users (username);
3. 創(chuàng)建復合索引
- 符合索引使用時必須遵循最左前綴原則,查詢時必須包含最左邊的列才能生效
-- 按順序:先按 category_id,再按 created_at 排序 CREATE INDEX idx_category_created ON products (category_id, created_at);
4. 在建表時直接定義索引
CREATE TABLE orders ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id INT NOT NULL, status VARCHAR(20), created_at DATETIME, -- 主鍵自動創(chuàng)建聚簇索引(InnoDB) INDEX idx_user_status (user_id, status), -- 普通復合索引 UNIQUE INDEX uk_order_no (order_no) -- 唯一索引 );
5. 添加主鍵(自動添加聚簇索引)
ALTER TABLE table_name ADD PRIMARY KEY (id);
到此這篇關(guān)于MySQL 慢查詢定位與 SQL 性能優(yōu)化實戰(zhàn)指南的文章就介紹到這了,更多相關(guān)mysql慢查詢內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mysql兩種情況下更新字段中部分數(shù)據(jù)的方法
Mysql更新字段中部分數(shù)據(jù)的兩種情況在下文給予詳細的解決方法,感興趣的朋友可以參考下哈2013-05-05
解決MySQL Sending data導致查詢很慢問題的方法與思路
這篇文章主要介紹了解決MySQL Sending data導致查詢很慢問題的方法與思路,感興趣的小伙伴們可以參考一下2016-04-04
MySQL中FIND_IN_SET()函數(shù)與in的區(qū)別及說明
文章介紹了SQL中FIND_IN_SET函數(shù)和IN關(guān)鍵字的區(qū)別及使用,FIND_IN_SET允許字段或常量作為參數(shù)并進行精確匹配,而IN只允許常量且進行完全匹配,文章指出使用FIND_IN_SET可能導致索引失效,從而增加查詢時間2025-10-10
解決MySQL啟動報錯:ERROR 2003 (HY000): Can''t connect to MySQL serv
這篇文章主要介紹了解決MySQL啟動報錯:ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061),本文解釋了如何解決該問題,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07
新裝MySql后登錄出現(xiàn)root帳號提示mysql ERROR 1045 (28000): Access denied
這篇文章主要介紹了新裝MySql后登錄出現(xiàn)root帳號提示mysql ERROR 1045 (28000): Access denied for use的解決辦法,需要的朋友可以參考下2017-01-01

