高併發系統中,單條低效查詢可佔用過量 CPU、I/O 與鎖資源,導致整個應用叢集回應變慢甚至雪崩。優化查詢既是科學也是藝術,MySQL 內建工具提供強大觀測與干預能力。本文聚焦三大核心技法。
CREATE INDEX idx_username ON users(username);
-- 或建表時
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(64),
INDEX idx_username (username)
);
SHOW INDEX FROM users;
(a,b,c) 可支援 a、a,b、a,b,c,不可跳過 a 直接用 b。Using index),避免回表。EXPLAIN SELECT * FROM country JOIN city ON city.countrycode = country.code WHERE country.name = 'Taiwan';
| 欄位 | 含義 | 優化關注點 |
|---|---|---|
| type | 存取類型 | 目標:ref/eq_ref/range;避免 ALL(全表掃描) |
| possible_keys | 可能用到的索引 | 為空表示無索引可用 |
| key | 實際使用的索引 | 與預期不符需分析 |
| key_len | 索引鍵長度 | 推斷複合索引用到第幾欄 |
| rows | 預估掃描行數 | 越小越好;配合 filtered 評估實際過濾效果 |
| Extra | 額外資訊 | Using where、Using index 佳;Using temporary、Using filesort 需優化 |
原查詢 EXPLAIN 顯示 city 表 type=ALL, rows=4019。建立索引 CREATE INDEX idx_ccode ON city(countrycode); 後,重新 EXPLAIN 顯示 type=ref, rows=333,掃描行數暴跌 92%,查詢延遲從秒級降至毫秒級。
| 參數 | 建議起始值 | 調校指引 |
|---|---|---|
innodb_buffer_pool_size | 實體記憶體 60~80% | 核心緩衝池,容納熱點資料與索引頁;監控 Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests 命中率 > 99%。 |
key_buffer_size (MyISAM) | 實體記憶體 10~25% | 若仍有 MyISAM 表;InnoDB 主流環境可設較小(32~64MB)。 |
read_buffer_size | 1~4 MB | 全表掃描時的序列讀取緩衝;大型報表查詢可適度調大至 8~16 MB。 |
table_open_cache | 4000+ (視 max_connections) | 配合 Opened_tables 狀態變數調整,避免頻繁開關表。 |
long_query_time | 0.5~1 秒 | 慢查詢日誌門檻;生產環境建議設 0 秒全記錄,配合 log_queries_not_using_indexes。 |
innodb_flush_log_at_trx_commit | 1 | 1=最高持久性;2=高效能(秒級丟失風險);0=最高效能(崩潰丟失 1 秒)。 |
sync_binlog | 1 | 配合上述參數保證雙 1 安全;極致效能可放寬但需評估 RPO。 |
EXPLAIN、執行時間、Rows examined。pt-query-digest 分析 Top N 慢查詢。SELECT *、拆分大事務、消除隱式轉換)。索引讓查找「有路可走」,EXPLAIN 讓執行「可視可控」,參數調校讓資源「用在刀口上」。三者結合,構成 MySQL 查詢優化的鐵三角。