本文系統闡述 MySQL 查詢優化的標準化三步驟:建立有效索引、EXPLAIN 分析執行計畫、調整關鍵配置參數,並以雙表關聯查詢為例,展示從全表掃描到索引覆蓋的劇效提升。
MySQL 支援 B-Tree 索引 (預設)、全文索引、空間索引。每表最多 64 個索引 (InnoDB),單一索引最多 16 欄位 (MySQL 5.7+)。
CREATE INDEX idx_username ON users(username);
-- 複合索引 (最左前綴原則)
CREATE INDEX idx_user_status ON users(username, status);
(a,b,c) 可支援 a、a,b、a,b,c 查詢,不可跳過 a 直接用 b,c。
EXPLAIN SELECT city.name, city.district
FROM city JOIN country ON city.countrycode = country.code
WHERE country.code = 'IND';
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | SIMPLE | country | const| PRIMARY | PRIMARY| 3 | const| 1 | Using index |
| 1 | SIMPLE | city | ALL | NULL | NULL | NULL | NULL | 4079 | Using where |
CREATE INDEX idx_countrycode ON city(countrycode);
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
| 1 | SIMPLE | country | const| PRIMARY | PRIMARY | 3 | const| 1 | Using index |
| 1 | SIMPLE | city | ref | idx_countrycode| idx_countrycode| 3 | const| 333 | Using where |
掃描行數從 4079 降至 333,**減少 91.8%**。
若查詢僅需索引欄位,Extra 顯示 Using index,完全避免回表:
CREATE INDEX idx_ccode_name ON city(countrycode, name, district);
-- 查詢
SELECT name, district FROM city WHERE countrycode = 'IND';
-- Extra: Using index
| 參數 | 建議 | 說明 |
|---|---|---|
| innodb_buffer_pool_size | 專用機 60~80% RAM | InnoDB 核心快取,命中率 > 99% 為佳 |
| key_buffer_size | MyISAM 為主時 20~25% RAM | MyISAM 索引快取 |
| table_open_cache | 4000+ (配合 max_connections) | 減少表定義開關開銷 |
| sort_buffer_size / read_buffer_size | 4M~16M | 排序/全掃描緩衝,每執行緒分配,勿設過大 |
| long_query_time | 0.5~1 秒 | 慢查詢門檻,配合 slow_query_log |
| query_cache_type | OFF (MySQL 5.7+ 建議) | 查詢快取在高併發下常成熱點鎖 |
slow_query_log=1, long_query_time=1)pt-query-digest)EXPLAINtype 是否為 ALL/index (需優化)rows 是否合理 (應遠小於總行數)Extra 是否有 Using temporary/Using filesort「索引是矛,EXPLAIN 是盾,參數是內功」。系統化執行「慢查詢收集 → EXPLAIN 診斷 → 索引/SQL/參數 三位一體優化 → 壓測驗證」,是 MySQL 效能調優的黃金法則。切勿盲目加索引或調參數,必須以執行計畫與監控指標為依據。