事故現場
- **時間窗口**:2014-03-12 15:39:01 ~ 15:55:00
- **現象**:某慢查詢執行極慢,阻塞後續 5000+ Queries,業務系統雪崩。
- **根因**:表存在 `dateline` 索引,優化器誤選該索引導致執行計劃災難。
優化前後對比
執行計劃
走 `dateline` 索引 (惡劣):
`type: ref` → `rows: 900,000+` (全表掃描級) → `Using where; Using temporary; Using filesort`
強制忽略 `dateline` (優秀):
`type: range` → `rows: ~200` → `Using index condition`
執行時間
- 誤用索引:**> 30 秒** (導致阻塞鏈)
- 正確索引:**< 10 ms**
處理過程
- **診斷**:`EXPLAIN` 發現優化器選錯索引。
- **猶豫**:未知該索引是否被其他查詢使用,擔心誤刪副作用。
- **決策**:經開發確認無其他查詢依賴,**果斷刪除** `DROP INDEX dateline ON table;`
- **觀察**:後續數週監控,**零負面影響**,慢查詢徹底消失。
核心心法
「索引是好東西,但不要貪。」
每個索引都是雙刃劍:寫入維護成本 + 優化器誤判風險。
**不該存在的索引就該幹掉,留著礙事。**
索引治理清單
- **定期審計**:`sys.schema_unused_indexes` (MySQL 5.7+ / 8.0) 找出長期未用索引。
- **審慎創建**:新增索引前 `EXPLAIN` 驗證,評估寫入開銷。
- **監控誤用**:慢查詢日誌 + `EXPLAIN` 發現優化器誤選 → `IGNORE INDEX` 或刪除。
- **覆蓋索引**:優先設計覆蓋索引減少回表,而非單列索引堆砌。
本案關鍵數據
- 表行數:~100 萬
- 誤用索引選擇度極低 (幾乎全表掃描)
- 正確索引選擇度高 (篩選 99%+ 數據)
- 阻塞鏈長度:5000+ 併發 Queries