mysql 性能優化之Explain講解

EXPLAIN是 MySQL 中用于分析查詢執行計劃的重要工具,通過它可以查看查詢如何使用索引、掃描數據的方式以及表連接順序等信息,從而找出性能瓶頸。以下是關于EXPLAIN的詳細介紹和實戰指南:

1. EXPLAIN 基本用法

SELECTINSERTUPDATEDELETE語句前加上EXPLAIN關鍵字即可查看執行計劃:

EXPLAIN SELECT * FROM users WHERE age > 18;

2. 關鍵字段解析

EXPLAIN返回的結果包含多個字段,重點關注以下幾個:

id
  • 查詢的標識符,數值越大優先級越高,相同數值按順序執行。
type
  • 數據訪問類型,從最優到最差排序:
    • system/const:單條記錄查詢(主鍵或唯一索引)。
    • eq_ref:唯一索引掃描(如JOIN操作)。
    • ref:非唯一索引掃描。
    • range:范圍掃描(如WHERE age > 18)。
    • index:全索引掃描(僅掃描索引樹)。
    • ALL:全表掃描(性能最差)。
possible_keys
  • 可能使用的索引,但不一定實際使用。
key
  • 實際使用的索引,若為NULL則未使用索引。
key_len
  • 索引使用的字節數,用于評估索引的選擇性。
rows
  • MySQL 估算的掃描行數,值越小越好。
Extra
  • 額外信息,常見值:
    • Using filesort:需額外排序(性能開銷大)。
    • Using temporary:使用臨時表(如GROUP BYORDER BY)。
    • Using index:覆蓋索引(僅通過索引即可獲取所有數據)。

3. 實戰優化案例

案例 1:全表掃描優化

問題 SQL

SELECT * FROM orders WHERE status = 'paid';

EXPLAIN 結果

+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
| 1  | SIMPLE      | orders | ALL  | NULL          | NULL | NULL    | NULL | 100000 | Using where |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+

分析type=ALL(全表掃描),key=NULL(未使用索引)。
優化

ALTER TABLE orders ADD INDEX idx_status (status);

優化后 EXPLAIN

+----+-------------+--------+------+---------------+----------+---------+-------+------+-------------+
| id | select_type | table  | type | possible_keys | key      | key_len | ref   | rows | Extra       |
+----+-------------+--------+------+---------------+----------+---------+-------+------+-------------+
| 1  | SIMPLE      | orders | ref  | idx_status    | idx_status | 152     | const | 500  | Using index |
+----+-------------+--------+------+---------------+----------+---------+-------+------+-------------+

結果type=ref(索引掃描),rows=500(掃描行數大幅減少),Using index(覆蓋索引)。

案例 2:復合索引優化

問題 SQL

SELECT user_id, amount FROM orders WHERE user_id = 100 AND status = 'paid';

EXPLAIN 結果

+----+-------------+--------+------+---------------+----------+---------+-------+------+-------------+
| id | select_type | table  | type | possible_keys | key      | key_len | ref   | rows | Extra       |
+----+-------------+--------+------+---------------+----------+---------+-------+------+-------------+
| 1  | SIMPLE      | orders | ref  | idx_user      | idx_user | 4       | const | 1000 | Using where |
+----+-------------+--------+------+---------------+----------+---------+-------+------+-------------+

分析:僅使用了user_id索引,未使用status條件。
優化:創建復合索引:

ALTER TABLE orders ADD INDEX idx_user_status (user_id, status);

優化后 EXPLAIN

+----+-------------+--------+------+-------------------+-------------------+---------+-------------+------+-------------+
| id | select_type | table  | type | possible_keys     | key               | key_len | ref         | rows | Extra       |
+----+-------------+--------+------+-------------------+-------------------+---------+-------------+------+-------------+
| 1  | SIMPLE      | orders | ref  | idx_user_status   | idx_user_status   | 156     | const,const | 50   | Using index |
+----+-------------+--------+------+-------------------+-------------------+---------+-------------+------+-------------+

結果rows=50(掃描行數進一步減少),Using index(覆蓋索引)。

案例 3:消除Using filesort

問題 SQL

SELECT * FROM products ORDER BY create_time LIMIT 10;

EXPLAIN 結果

+----+-------------+----------+------+---------------+------+---------+------+--------+----------------+
| id | select_type | table    | type | possible_keys | key  | key_len | ref  | rows   | Extra          |
+----+-------------+----------+------+---------------+------+---------+------+--------+----------------+
| 1  | SIMPLE      | products | ALL  | NULL          | NULL | NULL    | NULL | 100000 | Using filesort |
+----+-------------+----------+------+---------------+------+---------+------+--------+----------------+

分析:全表掃描后進行文件排序(Using filesort)。
優化:添加索引:

ALTER TABLE products ADD INDEX idx_create_time (create_time);

優化后 EXPLAIN

+----+-------------+----------+------+---------------+-------------------+---------+------+------+-------------+
| id | select_type | table    | type | possible_keys | key               | key_len | ref  | rows | Extra       |
+----+-------------+----------+------+---------------+-------------------+---------+------+------+-------------+
| 1  | SIMPLE      | products | index| NULL          | idx_create_time   | 5       | NULL | 10   | Using index |
+----+-------------+----------+------+---------------+-------------------+---------+------+------+-------------+

結果type=index(索引掃描),消除了Using filesort

4. 高級用法:EXPLAIN ANALYZE

MySQL 8.0+ 支持EXPLAIN ANALYZE,返回更詳細的執行信息,包括實際掃描行數和時間:

EXPLAIN ANALYZE SELECT * FROM users WHERE age > 18;

5. 優化建議

  1. 優先優化type字段:盡量避免ALLindex類型,目標是ref或更優。
  2. 確保key字段非NULL:通過創建索引讓查詢使用索引。
  3. 消除Using filesortUsing temporary:通過合理索引避免額外排序和臨時表。
  4. 利用覆蓋索引:讓Extra字段出現Using index,減少回表操作。
  5. 復合索引順序:將選擇性高的字段放在前面(如唯一值多的字段)。

6. 常見誤區

  • 索引越多越好:過多索引會增加寫操作開銷和內存占用。
  • 忽視復合索引順序:不滿足最左匹配原則會導致索引失效。
  • 過度依賴EXPLAIN估算rows是估算值,實際可能有偏差,需結合SHOW PROFILE等工具驗證。

通過EXPLAIN深入分析查詢執行計劃,針對性地優化索引和查詢語句,可以顯著提升 MySQL 性能。

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

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

相關文章

Redis 連接:深度解析與最佳實踐

Redis 連接:深度解析與最佳實踐 引言 Redis 作為一款高性能的內存數據結構存儲系統,在當今的互聯網應用中扮演著越來越重要的角色。高效的 Redis 連接管理對于保證系統的穩定性和性能至關重要。本文將深入探討 Redis 連接的原理、配置以及最佳實踐,幫助讀者更好地理解和應…

C語言---VSCODE的C語言環境搭建

文章目錄資源下載配置環境驗證資源下載 站內下載 配置環境 解壓壓縮包,復制以下文件的路徑 打開主頁搜索系統環境變量 點擊環境變量 選擇系統變量中的Path,點擊編輯 在最后面添加路徑。 添加完成記得關機重啟。 驗證 重啟電腦之后打開在Power…

ojdbc對應jdk版本附下載地址(截止20250722)

可以從Oracle官網查看, JDBC and UCP Downloads page

Redis為什么被設計成是單線程的?

Redis單線程模型解析 當我們說Redis是單線程時,特指"其網絡IO和鍵值對讀寫操作由單個線程完成"。實際上,Redis僅網絡請求模塊和數據操作模塊采用單線程設計,而持久化存儲、集群支持等其他模塊都采用了多線程架構。 事實上,Redis從4.0版本就開始對部分命令實現了…

基礎流程圖

一、常用符號及定義二、 畫圖基礎規則1、從上至下,從左至右流向順序。2、開始符號只能有一個出口。3、進程符號不做校驗邏輯。4、相同流程圖,符號大小應為一致。5、引用流程,不重復繪制。6、路徑符號盡量避免交叉重疊。7、同一路徑&#xff0…

C# 結構體

目錄 1.如何定義一個結構體(struct 關鍵字) 2.如何使用一個結構體 3.如何修改一個數據 4.如何讓去訪問一個學生的信息 5、結構體數組 練習 1.如何定義一個結構體(struct 關鍵字) C#中public 、private、protect的區別 結構…

在Python中操作Word

生成請假條1.準備一個文件“template.docx”,內容如下。2.安裝docxtpl庫。pip install docxtpl3.執行代碼,替換字典內容。from docxtpl import DocxTemplate# 讀取定義模板文件 tpl DocxTemplate(template.docx) # 創建子文檔 sd tpl.new_subdoc() # 添…

網絡協議(四)網絡層 路由協議

在網絡層及網絡層之上使用IP地址,IP地址放在IP數據報的首部,而MAC地址放在MAC幀的首部。通過數據封裝,把IP數據報分組封裝為MAC幀。 由于路由器的隔離,IP網絡中無法通過廣播MAC地址來完成跨網絡的尋址,因此在網絡層中只…

(后者可以節約內存/GPU顯存)Pytorch中求逆torch.inverse和解線性方程組torch.linalg.solve有什么關系

假設我們要求A的逆矩陣,正常情況下我們使用如下命令: torch.inverse(A)但是本人發現,這個函數還挺消耗顯存的。想到求逆矩陣和求線性方程組有很大關系。從而可以使用torch.linalg.solve來求解逆矩陣,關鍵是其顯存消耗小。 求解逆矩…

esp32 idf 使用http訪問json直接拼接content_length = -1

CMakeLists.txt添加網絡請求庫 REQUIRES esp_http_client效果圖D (14235) HTTP_CLIENT: content_length -1 需要直接拼接content_length才能打印#include <stdio.h> #include <string.h> #include "esp_log.h" #include "esp_system.h" #inc…

[Github】下載使用github上的源代碼

一、安裝Anoconda 二、安裝 Git &#xff08;1&#xff09;安裝 方法 1&#xff1a;通過 Git 官網安裝? 下載 Git for Windows&#xff1a;https://git-scm.com/download/win運行安裝程序&#xff0c;??確保勾選 "Add Git to PATH"??&#xff08;重要&#…

Java 邂逅 WebSocket:解鎖實時通信的無限可能?

在當今的互聯網時代&#xff0c;實時通信已經成為許多應用不可或缺的功能。從在線聊天工具到實時游戲互動&#xff0c;從股票行情推送再到物聯網數據傳輸&#xff0c;都對實時性有著極高的要求。而在 Java 技術棧中&#xff0c;WebSocket 技術的出現&#xff0c;為開發者打開了…

MySQL 核心知識點梳理(5)

目錄 事務 MySQL事務的四大特性 ACID 原子性 持久性 隔離性 事務的隔離級別 讀未提交 讀已提交 可重復讀 串行化 事務的隔離級別如何實現 MVCC 版本鏈 READVIEW 高可用 MySQL數據庫的讀寫分離 主從復制 主從同步延遲怎么處理 分庫策略 水平分庫分表的策略…

借助AI學習開源代碼git0.7之六write-tree

借助AI學習開源代碼git0.7之六write-tree write-tree.c 的作用是根據當前的索引&#xff08;cache&#xff09;內容創建一個樹&#xff08;tree&#xff09;對象&#xff0c;并將其寫入Git的對象數據庫。 樹對象代表了項目在某個時間點的目錄結構。 代碼的主要邏輯&#xff1a;…

開源 python 應用 開發(八)圖片比對

最近有個項目需要做視覺自動化處理的工具&#xff0c;最后選用的軟件為python&#xff0c;剛好這個機會進行系統學習。短時間學習&#xff0c;需要快速開發&#xff0c;所以記錄要點步驟&#xff0c;防止忘記。 鏈接&#xff1a; 開源 python 應用 開發&#xff08;一&#xf…

SeaTunnel 云倉連接器使用指南 | AI 助手解讀系列

最近體驗了一下 Deepwiki 的 AI 文檔生成功能&#xff0c;本文展示其自動生成的《SeaTunnel 云端數據倉庫連接器》文檔內容&#xff0c;歡迎大家一起“挑刺捉蟲”&#xff0c;看看 AI 寫技術文檔到底靠不靠譜&#xff1f; 本文檔介紹了 Apache SeaTunnel 的云數據倉庫連接器&a…

每日算法刷題Day51:7.21:leetcode 棧6道題,用時1h40min

二.進階 1.套路 2.題目描述 1.給你一個字符串 s 。它可能包含任意數量的 * 字符。你的任務是刪除所有的 * 字符。 當字符串還存在至少一個 * 字符時&#xff0c;你可以執行以下操作&#xff1a; 刪除最左邊的 * 字符&#xff0c;同時刪除該星號字符左邊一個字典序 最小的字…

網絡基礎DAY16-MSTP-VRRP

STP/RSTP的局限性1.所有VLAN共享一棵生成樹 2.無法實現不同VLAN在多條Trunk鏈路上的負載分擔 3.次優化二層路徑。MSTP的基本概念及優勢MSTP的定義MST域擁有相同MST配置標識的網橋構成的集合。 具體如何分辨是否是同一個域&#xff0c;就看域名&#xff0c;配置修訂號&#xff0…

freertos關鍵函數理解 uxListRemove

//刪除pxItemToRemove節點 UBaseType_t uxListRemove(ListItem_t *pxItemToRemove) { //The list item knows which list it is in. Obtain the list from the list item.//找到節點所在的鏈表//my_printf( "uxListRemove pxItemToRemove %#p\n", pxI…

C語言---番外篇(柔性數組)

前言&#xff1a; 由于這塊內容所謂綜合性比較高&#xff0c;有數組的知識&#xff0c;有結構體的知識&#xff0c;還有動態內存管理的知識&#xff0c;所以我就單獨寫一篇博客&#xff0c;此謂番外篇。 柔性數組的概念 定義在結構體的最后一個元素的位置且大小未知的數組就叫…