CREATE TABLE tt (id INT PRIMARY KEY, name CHAR(20)) ENGINE=InnoDB;
CREATE TABLE ttt (id INT, name CHAR(20)) ENGINE=InnoDB; -- 無主鍵/索引
INSERT INTO tt VALUES (1,'aaa'),(2,'bbb'),(3,'ccc');
INSERT INTO ttt VALUES (1,'aaa'),(2,'bbb'),(3,'ccc');
EXPLAIN SELECT * FROM tt WHERE id > 1;
輸出關鍵列解讀:
| 列 | 值 | 含義 |
|---|---|---|
| type | range | 索引範圍掃描,優於 ALL (全表掃描) |
| possible_keys | PRIMARY | 可用索引 |
| key | PRIMARY | 實際使用索引 |
| key_len | 4 | 索引鍵長度 (INT=4 字節) |
| rows | 2 | 預估掃描行數 (優化器統計信息) |
| Extra | Using where | 需在存儲引擎層過濾 WHERE 條件 |
結論: 有主鍵索引,優化器直接定位滿足條件的 2 行,極高效。
EXPLAIN SELECT * FROM ttt WHERE id > 1;
關鍵差異: type=ALL、key=NULL、rows=3。全表掃描 3 行。若表為 GB 級,IO/CPU 開銷災難性。
EXPLAIN SELECT * FROM tt WHERE name = 'aaa';
結果: type=ALL、rows=3。雖只有 1 行結果,但無 name 索引,仍需全表掃描。
SET profiling = 1;
SELECT * FROM tt;
SHOW PROFILE;
SHOW PROFILES;
典型階段耗時解讀:
Sending data:0.000148s — 數據傳輸佔比大,網絡/結果集大小敏感Opening tables、Table lock:微秒級,若偏高檢查 table_open_cache/鎖爭用optimizing、statistics:優化器成本,復雜聯接時關注SHOW PROFILES 歷史記錄: 可對比不同 SQL 總耗時,快速定位慢查詢。
(a,b,c) 支持 a、a,b、a,b,c,不支持 b、c、b,cSELECT a,b FROM tbl WHERE c=1 → 索引 (c,a,b) 避免回表WHERE YEAR(dt)=2024)、隱式轉換 (WHERE phone=13800000000 但 phone 是 VARCHAR)、!=/NOT IN/LIKE '%abc'| 列名 | 核心關注點 | 優化方向 |
|---|---|---|
| type | system > const > eq_ref > ref > range > index > ALL | 至少達到 range,最好 ref/eq_ref |
| key | 實際用索引 | NULL 表示無索引可用,需建索引 |
| key_len | 索引鍵長度 | 推斷聯合索引用了幾列 |
| rows | 預估掃描行數 | 越小越好,InnoDB 為估算值 |
| Extra | Using index/where/filesort/temporary | Using index 好;filesort/temporary 需優化 |
ANALYZE TABLE 更新統計,InnoDB 抽樣 8 頁,大表可能不準sys.statement_analysis、performance_schema.events_statements_summary_by_digestlong_query_time=1 + log_queries_not_using_indexes=ON,配合 pt-query-digest 分析SQL 優化的本質是「讓優化器找到最優路徑」。EXPLAIN 是眼睛,索引是腿,統計信息是地圖。掌握 type、key、rows、Extra 四大核心指標,結合左前綴、覆蓋索引、選擇性原則,90% 的慢查詢可通過加索引/改寫 SQL 解決。剩下 10% 需架構層面:分庫分表、讀寫分離、緩存策略、異步處理。