索引是查詢性能的倍增器,也是寫入性能的成本源。本文以問答形式,系統解答 16 個索引核心問題,覆蓋 B+ 樹原理、字段選型、Like 匹配邊界、聯合索引最左前綴、覆蓋索引、NULL 影響、SQL 注入防範,並附贈「板子 30 分鐘優化千萬級表」實戰案例。
快速定位行,避免全表掃描。MySQL 多數索引用 B+ 樹 存儲(空間索引用 R 樹,Memory 引擎支持 Hash)。
數據 = 書正文,CPU = 你,索引 = 書的目錄。查目錄定頁碼,直接翻頁,不必逐頁翻閱。
不是。三大代價:
① 寫入維護成本(增刷改都要更新索引)。
② 空間佔用(100 頁正文卻有 50 頁目錄?)。
③ 小表建索引反而更慢(讀 2 頁宣傳冊還查目錄?)。
TEXT/BLOB 可建前綴索引(INDEX idx_content(content(100)))。前綴匹配可用:WHERE name LIKE 'abc%' 走索引。
通配符開頭不可用:LIKE '%abc'、LIKE '%abc%' 全表掃描。
類比:成語詞典按拼音排序,查「一*」極快,查「*一」或「*一*」必逐頁翻。
<, <=, =, >, >=, BETWEEN, IN 可用。
<>, !=, NOT IN 通常不可用(全表掃描)。
INDEX idx_name(name(10))。MySQL 單表單次查詢只能用一個索引(Index Merge 例外但不可靠)。
單索引不可行 → 必須聯合索引。
順序原則:區分度高(基數大)的列放前面。
如 WHERE a=1 AND b=2,若 a 基數大於 b,建 INDEX idx_ab(a,b)。
WHERE a=1 → 走 INDEX(a,b)(最左前綴)。WHERE b=1 → 不走 (b 非最左)。(a,b) 通常無需再建 (a) 单列索引。LIKE '%abc'NOT IN, !=, <>WHERE MD5(pwd)='...' → 改為應用層計算或函數索引(8.0+)。WHERE idx=1 OR a=10(OR 通常打破索引)。mobile=13711112222(隱式轉換),必須 mobile='13711112222'。索引葉子節點已包含所有查詢列,無需回表 查聚簇索引。
實踐:只 SELECT 需要的列,避免 SELECT * 破壞覆蓋。
NULL 會導致索引失效/統計失真。設計階段用 -1、0、''、'unknown' 等業務含義值替代 NULL,列定義 NOT NULL。
SHOW INDEX FROM tbl; EXPLAIN SELECT ...; -- 關注 type, possible_keys, key, key_len, rows, Extra
幾千條數據、幾百 QPS 的新聞表,LIKE '%keyword%' 完全夠用,別上全文搜索引擎。CPU 比人腦強太多,先跑起來再優化。
所有動態參數必須用預處理,佔位符綁定變量,拒絕字符串拼接。
索引設計是藝術,更是工程。掌握這 16 條,你已超越 80% 的開發者。