索引是 MySQL 查詢性能的核心杠桿,但「建了索引就快」是危險誤區。本文梳理索引創建時機、模糊查詢對策、組合索引最左前綴原則、索引緩存配置、維護成本權衡五大核心細節,幫助開發者建立科學的索引策略。
當某列出現在以下位置時,優先評估建索引收益:
WHERE status = 1、WHERE create_time > '2024-01-01'ON a.user_id = b.idORDER BY create_time DESC、GROUP BY department_id反例:SELECT * FROM t WHERE id > 100(主鍵已隱含索引)、WHERE gender = 'M'(基數極低,全表掃描更快)。
LIKE 'abc%'(前綴固定)可用 B-Tree 索引範圍掃描。LIKE '%abc' / LIKE '%abc%'(前導通配符)不可用 普通索引,必走全表掃描。解決方案:
ALTER TABLE t ADD FULLTEXT INDEX ft_content (content); + MATCH(content) AGAINST('keyword' IN BOOLEAN MODE)。適用于自然語言文本,中文需分詞器插件(ngram/parser)。REVERSE(col) 列,查 LIKE 'cba%'。定義組合索引 INDEX idx_a_b_c (a, b, c),等價於擁有三個虛擬索引:(a)、(a,b)、(a,b,c)。
| WHERE 條件 | 索引使用情況 |
|---|---|
WHERE a = 1 | 用到 (a) |
WHERE a = 1 AND b = 2 | 用到 (a,b) |
WHERE a = 1 AND b = 2 AND c = 3 | 用到 (a,b,c)(覆蓋索引可能) |
WHERE a = 1 AND c = 3 | 用到 (a),c 斷層無法用到 |
WHERE b = 2 | 全表掃描,最左列 a 缺失 |
WHERE a = 1 ORDER BY b | 用到 (a,b),避免 filesort |
WHERE a = 1 GROUP BY b | 用到 (a,b),避免臨時表 |
Cardinality 越大,過濾效果越好。>, <, LIKE 'abc%')會阻斷後續列使用索引。SELECT a, b FROM t WHERE a=1 AND b=2,索引 (a,b) 直接覆蓋查詢,無需回表。| 引擎 | 緩存參數 | 建議值 | 監控指標 |
|---|---|---|---|
| MyISAM | key_buffer_size | 物理內存 20-25%(純 MyISAM 實例) | Key_read_requests / Key_reads > 100:1 |
| InnoDB | innodb_buffer_pool_size | 物理內存 60-80%(專用 DB 服務器) | Innodb_buffer_pool_read_requests / Innodb_buffer_pool_reads > 1000:1 |
InnoDB 將數據頁與索引頁統一緩存在 Buffer Pool,無需單獨配置索引緩存。innodb_buffer_pool_size 是 InnoDB 性能的單一最關鍵參數。
INSERT/UPDATE/DELETE 都需同步更新所有相關索引(B-Tree 分裂/合併、頁寫入)。mysqlreport / SHOW GLOBAL STATUS 關注 Com_insert, Com_update, Com_delete 佔比,評估讀寫比例。ANALYZE TABLE 更新統計信息,防止優化器誤判(Cardinality 過期導致錯誤索引選擇)。SELECT * FROM sys.schema_unused_indexes (MySQL 5.7+ sys schema) 發現無用索引。索引優化是「業務查詢模式驅動結構設計」的動態過程:
1. 慢查詢日誌發現問題 → 2. EXPLAIN 分析計劃 → 3. 按最左前綴設計/調整組合索引 → 4. 驗證讀寫權衡 → 5. 監控統計信息鮮度。
切記:沒有完美的索引,只有適合當前業務負載的索引。