| 模式 | 能否用索引 | 說明 |
xxx% | ✅ 是 | 前綴匹配,利用 B+ 樹有序性 |
%xxx / %xxx% | ❌ 否 | 前導通配符,無法利用索引順序 |
同理:<, <=, =, >, >=, BETWEEN, IN 可用索引;<>, !=, NOT IN 通常不可用。
6. 不適合建索引的場景
- 低基數列:性別、狀態、類型等(重複值超過 15% 通常不建)
- 超長字段:用前綴索引(如
INDEX(name(10)))
- 高頻更新列:維護成本過大
7. 單次查詢只能用一個索引
MySQL 5.6+ 引入 Index Condition Pushdown (ICP) 優化,但本質上仍是單索引掃描。
8. 多列查詢如何建索引?
核心原則:區分度高的列放前面。
- 方案 A:單列索引 a、b —— 優化器只會選一個
- 方案 B:聯合索引
(a,b) 或 (b,a) —— 區分度高者優先
9. 聯合索引最左前綴原理
INDEX(a,b,c)
WHERE a = 1 ✅ 用到索引
WHERE a = 1 AND b = 2 ✅ 用到索引
WHERE b = 2 ❌ 無法用到(非最左列)
WHERE a = 1 AND c = 3 ✅ 部分用到(僅 a)
有 (a,b) 通常不需再建單獨 (a)。
10. 導致索引失效的常見寫法
LIKE '%xxx'
NOT IN, !=, <>
- 列上做函數/運算:
WHERE MD5(pwd) = 'xxx'
WHERE idx=1 OR col=10(OR 兩側需都有索引)
- 字符串列存數值卻不加引號:
WHERE mobile = 13800000000 → 隱式轉換,索引失效
⚠️ 手機號請用 CHAR(11) 存儲,切勿用 INT(會丟失前導 0 且超出範圍)。
11. 覆蓋索引 —— 效能殺手鐧
查詢只需掃描索引樹即可獲取所有所需列,避免回表。
實踐: SELECT id, name FROM t WHERE age > 20 若有 INDEX(age, id, name) 即為覆蓋索引。
禁忌: 無必要勿用 SELECT *。
12. NULL 與索引
NULL 會導致索引統計不準、篩選複雜。建議:NOT NULL + 預設值(如 -1、空字串)替代。
13. 索引分析神器
SHOW INDEX FROM tbl;
EXPLAIN SELECT ...; -- 重點看 type、key、rows、Extra
善用 EXPLAIN 判斷是否走索引、是否發生 Using filesort/Using temporary。
14. 切勿過早優化
幾千筆資料的新聞表,每天幾百次全文搜尋,LIKE '%kw%' 完全能抗住,別上來就架 Elasticsearch。
15. 實戰案例:30 分鐘解決生產環境死效能
某中小企業官網(日 PV 2-3 萬),獨立伺服器,資料量 < 100 MB,頁面打不開。
外包報價 2 萬優化,DBA 花 20 分鐘給高頻查詢欄位加索引,世界安靜了。
16. 永遠記住:SQL 注入防範
參數化查詢、預編譯語句、最小權限原則——索引再好,安全漏洞一個就能毀了系統。
- 上一篇文章: JDBC 連接 MySQL 中文亂碼(問號)根因分析與完整解決方案
- 下一篇文章: SQL Server 死鎖根因深度解析與解決預防全攻略
Copyright ©
程式碼之家 All Rights Reserved