讓MySQL更快:EXPLAIN語句詳盡解析

前言

在數據庫性能調優中,SQL 查詢的執行效率是影響系統整體性能的關鍵因素之一。MySQL 提供了強大的工具——EXPLAIN 語句,幫助開發者和數據庫管理員深入分析查詢的執行計劃,從而發現潛在的性能瓶頸并進行針對性優化。

EXPLAIN 語句能夠模擬 MySQL 優化器的執行過程,返回查詢的詳細執行計劃,包括表的訪問順序、索引的使用情況、連接類型、掃描行數等關鍵信息。通過理解 EXPLAIN 的輸出,開發者可以快速定位低效查詢的問題所在,例如全表掃描、缺少索引、臨時表或文件排序等,并采取相應的優化措施。

本文將詳細介紹 EXPLAIN 的基本用法、輸出字段的含義,并通過實際案例演示如何利用 EXPLAIN 分析和優化 SQL 查詢。

微信圖片_20250524153711?

?

一、關于EXPLAIN語句

1.1 簡介

EXPLAIN 是 MySQL 提供的用于分析 SQL 查詢執行計劃的工具。它通過在 SELECT 語句前添加 EXPLAIN 關鍵字,使 MySQL 返回查詢的執行計劃,而不是實際執行查詢。執行計劃描述了 MySQL 如何訪問表、如何使用索引以及如何連接表等信息。

EXPLAIN 的主要作用包括:

  • 分析查詢性能:識別慢查詢的根源,例如全表掃描或索引未命中。
  • 驗證索引有效性:確認是否正確使用了索引,或者是否需要添加新的索引。
  • 優化查詢結構:調整查詢語句或表結構以提高執行效率。

?

1.2 語法

EXPLAIN 的基本語法如下:

EXPLAIN [EXTENDED] [FORMAT = {TRADITIONAL | JSON}] SELECT ...;  
  • EXTENDED:擴展輸出,顯示更多信息(如優化后的查詢語句)。
  • FORMAT = JSON:以 JSON 格式返回結果,便于解析和調試。

示例

在select前加explain關鍵字,MySQL會返回該查詢的執行計劃而不是執行這條SQL

mysql> explain select * from student where id=1;
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table   | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | student | const | PRIMARY       | PRIMARY | 4       | const |    1 | NULL  |
+----+-------------+---------+-------+---------------+---------+---------+-------+------+-------+
1 row in set

?

image?

?

二、Explain列的含義

EXPLAIN 的輸出結果包含多個字段,每個字段提供了不同的信息。以下是關鍵字段的詳細說明:

2.1 概覽

以下是 MySQL ?EXPLAIN?? 輸出列的詳細說明,包括每列的定義、示例值、優化目標及判斷標準,幫助你深入理解查詢執行計劃:

列名作用描述優化目標(好的輸出特征)
id查詢的執行順序標識符子查詢或復雜查詢時,id 值高的先執行
select_type查詢類型(簡單查詢、子查詢、UNION 等)?SIMPLE? 或 PRIMARY? 表示簡單或主查詢
table當前操作的表名(包括臨時表或派生表)表名清晰,避免過多 <derived>? 或 <union>?
partitions匹配的分區(若表有分區)分區裁剪合理,避免全分區掃描
type數據訪問方式(關鍵性能指標)?const?、eq_ref?、ref?、range? 優于 ALL?
possible_keys可能用到的索引包含實際使用的索引
key實際使用的索引明確顯示有效索引名,非 NULL?
key_len索引使用的字節數與索引字段長度匹配,避免未完全使用索引
ref與索引比較的列或常量?const? 或關聯字段,避免 NULL?
rows預估掃描的行數(估算值)數值越小越好
filtered查詢條件過濾后剩余行的百分比百分比高(接近 100%)
Extra額外執行信息(關鍵優化提示)出現 Using index?,避免 Using filesort?

?

2.2 每列詳細說明及優化建議

1. id

  • 含義:查詢的標識符,表示查詢中 SELECT? 子句的執行順序。
    查詢的序列號,標識執行順序。相同 id? 按從上到下執行;不同 id? 時,值大的先執行(如子查詢)。

  • 示例

    EXPLAIN SELECT * FROM (SELECT * FROM t1) AS t_derived JOIN t2 ON t1.id = t2.id;
    
    • id=1?:派生表 t_derived?(子查詢)。
    • id=1?:主查詢 t2?。
  • 優化目標
    避免多層嵌套子查詢(id? 過多),減少復雜查詢。

  • 單一查詢(無子查詢或 UNION?)時,id? 為 1?。

  • 復雜查詢中,id? 的層級清晰,避免嵌套過深。

?

2. select_type

  • 含義:查詢的類型,描述查詢的復雜度。

  • |常見值及優化建議:|||

    說明理想情況
    SIMPLE簡單查詢,不包含子查詢或 UNION?。最佳,避免復雜嵌套。
    PRIMARY最外層查詢。正常,需關注其依賴的子查詢。
    SUBQUERY子查詢中的第一個 SELECT?。盡量避免,可考慮改寫為連接查詢。
    DEPENDENT SUBQUERY子查詢依賴外部查詢結果。高風險,可能導致性能下降。
    UNION?UNION? 中的第二個或后續查詢。正常,需注意 UNION? 結果集。
    UNION RESULT?UNION? 的結果集。正常,需檢查是否需要額外處理。
    DERIVED派生表(FROM? 子句中的子查詢)。需檢查派生表的性能。
    MATERIALIZED物化子查詢(MySQL 8.0+)。正常,但需確認物化效果。

?

3. table

  • 含義:當前查詢涉及的表名。

  • 理想輸出

    • 表名明確,避免派生表(如 <derivedN>?)或臨時表(如 <union1,2>?)。
    • 若出現派生表,需檢查子查詢是否可優化為連接查詢。

?

4. partitions

  • 含義:查詢涉及的分區(如果表是分區表)。

    表示查詢涉及的分區情況。當表是分區表時,這個列會顯示匹配的分區。例如,一個表按照日期字段進行分區,查詢中指定了日期范圍,那么 partitions 列就會顯示涉及到的分區編號或者分區名稱。

  • 理想輸出

    • 分區表中僅掃描相關分區(如 p1?),而非全表掃描。

    • 若為 NULL?,表示表未分區或未使用分區。

      如果表是分區表,希望 partitions 列顯示的分區范圍盡量小。這樣可以減少查詢需要掃描的數據量,提高查詢效率。例如,如果一個分區表有 100 個分區,而查詢只涉及到其中的 1 - 2 個分區,這就是比較理想的輸出。

?

5. type

  • 含義:連接類型(訪問方法),反映 MySQL 如何查找表中的行。

  • 性能排序(從優到劣)

    1. system:表僅一行(系統表),是 const? 的特例。
    2. const:通過主鍵或唯一索引等值查詢,最多匹配一行。
    3. eq_ref:使用主鍵或唯一索引進行等值連接(如 JOIN?)。
    4. ref:使用非唯一索引進行等值查詢。
    5. range:索引范圍查詢(如 BETWEEN?、>?、<?)。
    6. index:全索引掃描(比全表掃描快)。
    7. ALL:全表掃描(最差)。
  • 優化建議

    • 目標是達到 const?、eq_ref? 或 ref?。
    • 避免 ALL?,需添加索引或優化查詢條件。

?

6. possible_keys

  • 含義:可能使用的索引(候選索引)。

  • 理想輸出

    • 顯示多個候選索引(說明索引設計合理)。

    • 若為 NULL?,表示無可用索引,需添加索引。

      列出與查詢條件相關的索引。

?

7. key

  • 含義:實際使用的索引。如果 key? 為 NULL?,表示沒有使用索引,可能是全表掃描。

  • 理想輸出

    • 明確顯示使用的索引(如 idx_name?)。
    • 若為 NULL?,表示未使用索引,需檢查 possible_keys? 并優化索引。
    • 顯示與 possible_keys? 中相同的索引,說明 MySQL 選擇了合適的索引。

?

8. key_len

  • 含義:使用的索引長度(字節數)。

  • 理想輸出

    • 值越小越好(表示使用的索引列越少或數據類型更緊湊)。
    • 例如,VARCHAR(100)? 使用 utf8mb4? 編碼時,最大占用 400? 字節。

?

9. ref

  • 含義:顯示索引的哪一列被使用,以及與之比較的值(常量或列名)。

    • 顯示哪些列或常量被用于查找索引列上的值。常見值包括:

    const?:使用常量值。

    表的列名:使用其他表的列進行比較。

  • func?:使用函數結果。

  • 理想輸出

    • 顯示具體的列名或常量(如 const?),表明索引有效。
    • 若為 func? 或 NULL?,可能表示索引未正確使用。
    • 顯示具體的列名或常量,表明索引被有效利用。

?

10. rows(估計掃描行數)

  • 含義:MySQL 估計需要掃描的行數。

  • 理想輸出

    • 值越小越好(表示過濾條件越精確)。例如,如果一個查詢估算只需要檢查 10 行就可以得到結果,這比估算檢查 10000 行要好得多。這表明查詢能夠快速定位到所需的數據行。
    • 若值過大(如 100000?),需優化索引或查詢條件。

?

11. filtered

  • 含義:表示查詢條件過濾的行百分比(MySQL 5.7+)。該值表示查詢掃描的行中有多少被篩選掉,值的范圍是 0 到 100。

    • 表示在存儲引擎返回的行中,經過 MySQL 服務器層過濾后,實際滿足查詢條件的行的比例。它是基于表統計信息和索引統計信息的一個估算值。
  • 理想輸出

    • 值越高越好(如 100%? 表示無過濾條件)。
    • 若值較低(如 10%?),說明查詢條件未充分利用索引。
    • filtered 的值應該盡可能高。例如,如果 filtered 的值是 90%,意味著存儲引擎返回的行中有 90% 的行滿足查詢條件,這比 filtered 值為 10% 的情況要好,因為減少了不必要的數據處理。

?

12. Extra

  • 含義:額外信息,提供查詢執行的附加說明,幫助診斷查詢執行的細節
  • |常見值及優化建議:|||
    說明優化建議
    Using index使用覆蓋索引(查詢列全部命中索引)。無需回表,性能最佳。
    Using where使用 WHERE? 條件過濾數據。正常,但需檢查過濾條件效率。
    Using temporary需要創建臨時表(如 ORDER BY? 和 GROUP BY? 一起使用)。避免,優化查詢或添加索引。
    Using filesort需要額外排序操作(如 ORDER BY? 未使用索引)。避免,優化排序字段索引。
    Distinct優化了 DISTINCT? 查詢。正常,無需額外優化。
    Range checked for each record未找到合適索引,需逐行檢查。添加合適索引。

?

  • 良好輸出:希望出現像 “Using index” 這樣的提示,這表明查詢效率較高。盡量避免出現 “Using temporary” 和 “Using filesort”,因為它們表示需要額外的資源開銷來處理查詢,如臨時表和文件排序,這可能會降低查詢性能。

?

?

三、優化建議及示例

3.1 優化建議

  1. 關注 ?type?? :確保查詢達到 const?、eq_ref? 或 ref? 級別,避免 ALL?。
  2. 優化 ?Extra?? :避免 Using filesort? 和 Using temporary?。
  3. 分析 ?key?? ?possible_keys??:確認是否使用了預期的索引。
  4. 減少掃描行數:通過索引或優化查詢條件降低 rows? 值。
  5. 檢查 ?filtered??:確保過濾條件有效,提高查詢效率。

?

3.2 優化示例

全表掃描

場景:全表掃描(type=ALL?)

  • 問題 SQL

    EXPLAIN SELECT * FROM users WHERE phone = '123456789';
    
  • 輸出type=ALL?,key=NULL?。

  • 優化:為 phone? 字段添加索引:

    ALTER TABLE users ADD INDEX idx_phone(phone);
    
  • 優化后輸出type=ref?,key=idx_phone?,rows=1?。

?

?

多表連接優化(Using join buffer)

問題描述

多表連接時出現 Using join buffer?,性能低下。

原SQL

SELECT u.name, o.order_no 
FROM users u 
JOIN orders o ON u.id = o.user_id 
WHERE u.age > 25 AND o.status = 'completed';

EXPLAIN 分析

EXPLAIN SELECT u.name, o.order_no FROM users u JOIN orders o ON u.id = o.user_id WHERE u.age > 25 AND o.status = 'completed';

輸出結果

id | select_type | table | type | possible_keys | key        | rows | Extra
---|-------------|-------|------|---------------|------------|------|-------------------
1  | SIMPLE      | u     | ALL  | idx_age       | NULL       | 1000 | Using where
1  | SIMPLE      | o     | ref  | idx_user_id   | idx_user_id| 500  | Using where; Using join buffer (Block Nested Loop)

問題診斷

  • users 表 type=ALL:未使用索引,全表掃描。
  • orders 表 Using join buffer:連接時未使用索引,性能差。

?

優化方案

  1. ?users.age?? 創建索引

    ALTER TABLE users ADD INDEX idx_age (age);
    
  2. ?orders.user_id?? ?orders.status?? 創建索引

    ALTER TABLE orders ADD INDEX idx_user_id_status (user_id, status);
    
  3. 調整查詢

    SELECT u.name, o.order_no 
    FROM users u 
    JOIN orders o ON u.id = o.user_id 
    WHERE u.age > 25 AND o.status = 'completed';
    
  4. 驗證優化效果

    EXPLAIN SELECT u.name, o.order_no FROM users u JOIN orders o ON u.id = o.user_id WHERE u.age > 25 AND o.status = 'completed';
    

    優化后輸出

    id | select_type | table | type | possible_keys         | key                  | rows | Extra
    ---|-------------|-------|------|-----------------------|----------------------|------|---------
    1  | SIMPLE      | u     | range| idx_age               | idx_age              | 500  | Using where
    1  | SIMPLE      | o     | ref  | idx_user_id_status    | idx_user_id_status   | 200  | Using where
    

效果

  • users 表 type=range:使用索引范圍掃描。
  • orders 表 Using join buffer 消失:連接直接通過索引完成。

?

結束語

EXPLAIN?語句是MySQL查詢優化的核心工具,如同數據庫工程師的"聽診器"。通過本文的詳細解析,相信您已經掌握了各輸出列的精髓。但需要強調的是,真正的優化功力需要在實踐中不斷積累。建議每次執行重要查詢時養成查看執行計劃的習慣,結合業務場景靈活運用索引策略、查詢重寫等手段。記住:優秀的數據庫性能不是偶然,而是源于對每個執行細節的精心雕琢。

?

求點關注-gif動圖 138_愛給網_aigei_com?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/82442.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/82442.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/82442.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java基礎 Day20

一、HashSet 集合類 1、簡介 HashSet 集合底層采取哈希表存儲數據 底層是HashMap 不能使存取有序 JDK8之前的哈希表是數組和鏈表&#xff0c;頭插法 JDK8之后的哈希表是數組、鏈表和紅黑樹&#xff0c;尾插法 2、存儲元素 &#xff08;1&#xff09;如果要保證元素的唯…

2505C++,32位轉64位

原文 假設有個想要將一個32位值傳遞給一個帶64位值的函數的函數.你不關心高32位的內容,因為該值是傳遞給回調函數的直通值,回調函數會把它截斷為32位值. 因此,你都擔心編譯器一般生成的將32位值擴展到64位值的那條指令的性能影響. 我懷疑這條指令不是程序中的性能瓶頸. 我想出…

光伏電站及時巡檢:守護清潔能源的“生命線”

在“雙碳”目標驅動下&#xff0c;光伏電站作為清潔能源的主力軍&#xff0c;正以年均20%以上的裝機增速重塑全球能源格局。然而&#xff0c;這些遍布荒漠、屋頂的“光伏矩陣”并非一勞永逸的能源提款機&#xff0c;其穩定運行高度依賴精細化的巡檢維護。山東棗莊觸電事故、衢州…

C++初階-list的使用2

目錄 1.std::list::splice的使用 2.std::list::remove和std::list::remove_if的使用 2.1remove_if函數的簡單介紹 基本用法 函數原型 使用函數對象作為謂詞 使用普通函數作為謂詞 注意事項 復雜對象示例 2.2remove與remove_if的簡單使用 3.std::list::unique的使用 …

OpenHarmony平臺驅動使用(一),ADC

OpenHarmony平臺驅動使用&#xff08;一&#xff09; ADC 概述 功能簡介 ADC&#xff08;Analog to Digital Converter&#xff09;&#xff0c;即模擬-數字轉換器&#xff0c;可將模擬信號轉換成對應的數字信號&#xff0c;便于存儲與計算等操作。除電源線和地線之外&#…

CSS【詳解】彈性布局 flex

適用場景 一維&#xff08;行或列&#xff09;布局 基本概念 包裹所有被布局元素的父元素為容器 所有被布局的元素為項目 項目的排列方向&#xff08;垂直/水平&#xff09;為主軸 與主軸垂直的方向交交叉軸 容器上啟用 flex 布局 將容器的 display 樣式設置為 flex 或 i…

基于MATLAB實現傳統譜減法以及兩種改進的譜減法(增益函數譜減法、多帶譜減法)的語音增強

基于MATLAB實現傳統譜減法以及兩種改進的譜減法&#xff08;增益函數譜減法、多帶譜減法&#xff09;的語音增強代碼示例&#xff1a; 傳統譜減法 function enhanced traditional_spectral_subtraction(noisy, fs, wlen, inc, NIS, a, b)% 參數說明&#xff1a;% noisy - 帶…

symbol【ES6】

你一閉眼世界就黑了&#xff0c;你不是主角是什么&#xff1f; 目錄 什么是Symbol&#xff1f;?Symbol特點?&#xff1a;創建方法&#xff1a;注意點&#xff1a;不能進行運算&#xff1a;顯示調用toString() --沒有意義隱式轉換boolean 如果屬性名沖突了怎么辦&#xff1f;o…

LeetCode 649. Dota2 參議院 java題解

https://leetcode.cn/problems/dota2-senate/description/ 貪心。不會寫。 class Solution {public String predictPartyVictory(String senate) {boolean rtrue,dtrue;int flag0;//flag>0,d前面有r;flag<0,r前面有dchar[] senatessenate.toCharArray();//每一輪while(r…

機器學習第二十二講:感知機 → 模仿大腦神經元的開關系統

機器學習第二十二講&#xff1a;感知機 → 模仿大腦神經元的開關系統 資料取自《零基礎學機器學習》。 查看總目錄&#xff1a;學習大綱 關于DeepSeek本地部署指南可以看下我之前寫的文章&#xff1a;DeepSeek R1本地與線上滿血版部署&#xff1a;超詳細手把手指南 感知機詳解…

maven快速上手

之前我們項目如果要用到其他額外的jar包&#xff0c;需要自己去官網下載并且導入。但是有maven后&#xff0c;直接在maven的pom.xml文件里用代碼配置即可&#xff0c;配置好后maven會自動幫我們聯網下載并且會自動導入該jar包 在右邊的maven中&#xff0c;我們可以看到下載安裝…

科學養生指南:解鎖健康生活密碼

健康是人生最寶貴的財富&#xff0c;在快節奏的現代生活中&#xff0c;科學養生成為保持良好狀態的關鍵。遵循現代醫學與營養學的研究成果&#xff0c;無需依賴傳統中醫理論&#xff0c;我們也能找到適合自己的養生之道。? 均衡飲食是健康的基石。現代營養學強調 “食物多樣&…

Qt狀態機QStateMachine

QStateMachine QState 提供了一種強大且靈活的方式來表示狀態機中的狀態&#xff0c;通過與狀態機類(QStateMachine)和轉換類(QSignalTransition&#xff0c; QEventTransition)結合&#xff0c;可以實現復雜的狀態邏輯和用戶交互。合理使用嵌套狀態機、信號轉換、動作與動畫、…

C++八股 —— 原子操作

文章目錄 1. 什么是原子操作2. 原子操作的特點3. 原子操作的底層原理4. 內存序內存屏障 5. 原子操作和互斥鎖的對比6. 常用的原子操作7. 相關問題討論 參考&#xff1a; C atomic 原子操作_c 原子操作-CSDN博客DeepSeek 1. 什么是原子操作 原子操作&#xff08;Atomic Opera…

雙紫擒龍紫紫紅指標源碼學習,2025升級版紫紫紅指標公式-重點技術

VAR1:MA((LOWHIGHCLOSE)/3,5); VAR2:CLOSEHHV(C,4) AND REF(C,1)LLV(C,4); 雙紫擒龍:REF(C,1)LLV(C,4) AND C>REF(C,2) OR REF(C,2)LLV(C,4) AND REF(C,1)<REF(C,3) AND REF(C,2)<REF(C,4) AND C>REF(C,1); VAR4:VAR1>REF(VAR1,1) AND REF(VAR1,1)<REF(VAR1,…

NeuralRecon技術詳解:從單目視頻中實現三維重建

引言 三維重建是計算機視覺領域中的一項關鍵技術&#xff0c;它能夠從二維圖像中恢復出三維形狀和結構。隨著深度學習的發展&#xff0c;基于學習的方法已經成為三維重建的主流。NeuralRecon是一種先進的三維重建方法&#xff0c;它能夠從單目視頻中實時生成高質量的三維模型。…

Ubuntu 上開啟 SSH 服務、禁用密碼登錄并僅允許密鑰認證

1. 安裝 OpenSSH 服務 如果尚未安裝 SSH 服務&#xff0c;運行以下命令&#xff1a; sudo apt update sudo apt install openssh-server2. 啟動 SSH 服務并設置開機自啟 sudo systemctl start ssh sudo systemctl enable ssh3. 生成 SSH 密鑰對&#xff08;本地機器&#xf…

MySQL 索引的增刪改查

MySQL 索引的增刪改查 1 建表時創建索引 [UNIQUE|FULLTEXT|SPATIAL] INDEX|KEY [別名] (字段名 [(長度)] [ASC|DESC] )主鍵直接寫&#xff1a; PRIMARY KEY (Id)例如&#xff1a; CREATE TABLE people (id int NOT NULL PRIMARY KEY AUTO_INCREMENT,last_name varchar(10)…

為什么現代CSS應該選擇OKLCH:從顏色科學到設計系統革新

在數字界面中&#xff0c;顏色不僅是美學的載體&#xff0c;更是信息傳遞的重要工具。CSS Color Level 4 標準引入了 OKLCH 顏色空間, 提供??感知均勻性??&#xff08;顏色差異與實際視覺感受一致&#xff09;&#xff0c;解決傳統HSL/HSV在調整顏色時的不自然問題。文本幫…

【java】小練習--零錢通

文章目錄 前言一、項目開發流程說明二、功能實現2.1 菜單2.2 零錢通明細2.3 零錢通收益2.4 零錢通消費2.5 零錢通退出確認2.6 零錢通金額校驗2.7 完整代碼 三、零錢通OOP版 前言 本文是我跟著B站韓順平老師的 Java 教程學習時動手實現“零錢通”項目的學習筆記&#xff0c;主要…