Explain

資料庫 EXPLAIN 指令結果值的詳細解釋。

MySQL EXPLAIN

select_type 詳細說明

類型說明
SIMPLE簡單查詢,不包含子查詢或 UNION。執行效率較高
PRIMARY最外層的 SELECT 查詢
UNIONUNION 中第二個或後續的 SELECT 語句
DEPENDENT UNIONUNION 中的 SELECT,其執行依賴於外部查詢結果
UNION RESULTUNION 查詢的結果集(臨時表)
SUBQUERY出現在 SELECT 列表、WHERE 或 HAVING 子句中的首個子查詢
DEPENDENT SUBQUERY依賴於外部查詢的子查詢,每次外部查詢產生一行都會重新執行
DERIVED派生表(FROM 子句中的子查詢),結果會實體化到臨時表
MATERIALIZED物化子查詢,MySQL 5.6+ 的優化技術
UNCACHEABLE SUBQUERY無法緩存的子查詢(如使用隨機函數、用戶變數)
UNCACHEABLE UNION包含無法緩存的 UNION 查詢

type 詳細說明(效率由高到低)

類型說明
system表中只有一行記錄(const 的特例)
const使用主鍵或唯一索引等值查詢,最多匹配一行
eq_ref使用主鍵或唯一非空索引連接查詢,對於前表每行組合讀取一行
ref非唯一索引掃描,返回匹配某單個值的所有行
fulltext使用全文索引執行查詢
ref_or_null類似 ref,但另外搜尋包含 NULL 值的行
index_merge使用索引合併優化,同時使用多個索引並合併結果
unique_subquery用於 IN 子查詢的優化,替代 eq_ref
index_subquery類似 unique_subquery,但用於非唯一索引
range僅檢索指定範圍內的行(=, <>, >, >=, <, <=, BETWEEN, IN 等)
index全索引掃描,和全表掃描幾乎一樣差
ALL全表掃描,效率最低

Extra 欄位詳細說明

說明
Using index覆蓋索引,只使用索引樹中的信息,大幅提高性能
Using where使用 WHERE 子句過濾,在 MySQL 服務器層面過濾
Using temporary創建臨時表處理查詢(排序、分組、多表連接)
Using filesort使用外部排序而非索引順序讀取,潛在性能問題
Using join buffer使用連接緩衝提高連接效率
Impossible WHEREWHERE 子句總是 false,不返回任何行
Select tables optimized away聚合函數可從索引直接獲得結果
No tables used查詢不涉及表(如 SELECT 1+1
Using index condition索引條件下推(ICP),減少檢索行數
Using MRR多範圍讀取優化,減少隨機 I/O

rows 與 filtered 值解讀

rows:MySQL 估計需要檢查的行數,越低越好。在 JOIN 操作中為嵌套循環所需讀取行數的乘積。

filtered:表條件過濾後剩餘的行百分比。例如 filtered=50.00 表示 WHERE 條件將過濾掉約 50% 的行。實際要檢查的行:rows × filtered%

PostgreSQL EXPLAIN

節點類型詳細解釋

類型說明
Seq Scan順序掃描,從頭到尾讀取整個表
Index Scan索引掃描,先掃描索引再訪問表數據
Index Only Scan僅索引掃描,所有數據都在索引中,最高效
Bitmap Scan位圖掃描,先創建匹配行的位圖,再按磁盤順序獲取
Nested Loop嵌套循環連接,對外表每行掃描內表
Hash Join哈希連接,建立哈希表後查找匹配
Merge Join合併連接,兩表按連接列排序後並行掃描
Sort排序操作
Limit限制返回行數
Aggregate聚合函數操作(SUM、COUNT 等)

cost 值的詳細含義

  • 數值單位:以任意磁盤頁面獲取為單位
  • startup cost:產生第一個輸出行前的初始化成本
  • total cost:產生所有輸出行的總成本
cost=0.42..1.42 rows=10 width=14
  • 0.42:產生第一行的成本
  • 1.42:產生所有 10 行的總成本
  • 每行平均寬度 14 字節

actual time(使用 EXPLAIN ANALYZE)

actual time=0.015..0.018 rows=10 loops=1
  • 0.015ms:獲得第一行的時間
  • 0.018ms:處理所有行的總時間
  • loops:節點執行次數
  • 總實際時間 = actual time × loops

緩衝區信息(使用 EXPLAIN (ANALYZE, BUFFERS))

指標說明
shared hit從共享緩衝區讀取的塊數(數據在內存中)
shared read從磁盤讀取到共享緩衝區的塊數(物理 I/O)
shared dirtied被查詢修改的共享緩衝區塊數
shared written從共享緩衝區寫入磁盤的塊數
temp read/written臨時文件讀寫,可能導致性能問題

Filter 與 Index Cond 的區別

  • Index Cond:使用索引直接找到匹配行,更高效
  • Filter:獲取行後再應用過濾,無法使用索引

MongoDB EXPLAIN

verbosity 模式

模式說明
queryPlanner默認模式,只顯示查詢計劃不執行
executionStats包含執行統計,實際執行查詢
allPlansExecution包含所有考慮過的計劃,最詳細

stage 詳細說明

Stage說明性能
COLLSCAN集合掃描,掃描所有文檔❌ 最低
IXSCAN索引掃描,通過索引鍵查找✅ 高效
FETCH從索引獲取信息後讀取文檔中等
SORT內存排序,無法使用索引時出現⚠️ 潛在問題
LIMIT限制返回文檔數
SKIP跳過指定數量文檔⚠️ 大量 SKIP 有性能問題
IDHACK使用 _id 字段特殊優化查詢✅ 高效
COUNT_SCAN使用索引計數,無需訪問文檔
PROJECTION_COVERED所有字段都在索引中✅ 最高效

executionStats 主要指標

指標說明
nReturned返回客戶端的文檔數
executionTimeMillis執行時間(毫秒)
totalKeysExamined掃描的索引鍵總數
totalDocsExamined掃描的文檔總數(理想應接近 nReturned)

查詢效率判斷標準

最佳情況nReturned ≈ totalKeysExamined ≈ totalDocsExamined
  • 索引覆蓋查詢:totalKeysExamined > 0 且 totalDocsExamined = 0
  • 索引效率:totalKeysExamined / nReturned 比率應接近 1:1
  • 文檔掃描效率:totalDocsExamined / nReturned 比率應接近 1:1

危險訊號

  • COLLSCAN 在大集合上
  • totalDocsExamined » nReturned(掃描了遠多於需要的文檔)
  • 高 executionTimeMillis 但低 nReturned
  • SORT 階段且 memUsage 接近 memLimit

查詢優化典型案例

COLLSCAN 改進

問題: { stage: "COLLSCAN", totalDocsExamined: 10000, nReturned: 10 }
解決: 為查詢條件創建適當索引

索引效率低下

問題: { stage: "IXSCAN", totalKeysExamined: 5000, nReturned: 10 }
解決: 創建更精確的複合索引或調整查詢

排序不使用索引

問題: { stage: "SORT", executionTimeMillis: 500, memUsage: 30000000 }
解決: 創建包含排序字段的索引

SKIP 效率問題

問題: 使用大量 SKIP 進行分頁
解決: 使用基於上次查詢結果的條件(如 { _id: { $gt: lastId } })

相關主題