複合索引 (col1, col2, col3) 的列順序、ORDER BY 排序方向、WHERE 條件匹配程度,直接決定索引是否生效。本文通過實測 EXPLAIN 對比,總結出三大鐵律,並給出優/劣模式速查表。
-- 表 dlog_user 主鍵 username,有復合索引 idx_online_status(username, online_status)
SELECT * FROM dlog_user ORDER BY online_status, username;
| 測試條件 | 索引定義 | EXPLAIN type | Extra | 結論 |
|---|---|---|---|---|
| 無額外索引 | 僅主鍵 | ALL | Using filesort | 全表掃描+排序 |
加索引 (username, online_status) | 同 SQL 順序 | ALL | Using filesort | **索引無效** |
調整索引 (online_status, username) | 匹配 ORDER BY 順序 | index | (空) | **索引生效** |
SQL 改為 ORDER BY online_status DESC, username | (online_status, username) | ALL | Using filesort | **排序方向不一致導致失效** |
ORDER BY a, b 需索引 (a, b),(b, a) 無效。ASC 或全 DESC,混用 ASC, DESC 導致索引失效(MySQL 8.0 前)。WHERE a=1 ORDER BY b 需索引 (a, b);WHERE a>1 ORDER BY b 範圍條件斷開最左前綴,索引部分失效。KEY a(a,b,c))| SQL 模式 | 索引效果 | 說明 |
|---|---|---|
WHERE a=10 AND b>50 | 優 | 最左前綴 a= 常量,b 範圍用到索引 |
WHERE a>10 AND b=50 | 劣 | a 範圍斷開前綴,b 無法用索引 |
ORDER BY a | 優 | 索引順序掃描 |
ORDER BY b | 劣 | 非最左列排序需 filesort |
WHERE a=10 ORDER BY a | 優 | 常量過濾 + 索引順序 |
WHERE a=10 ORDER BY b | 優 | a= 常量,b 索引順序 |
WHERE a=10 ORDER BY c | 劣 | 跳過 b 排序 c 需 filesort |
WHERE a>10 ORDER BY a | 優 | 範圍但同列排序可用索引 |
WHERE a>10 ORDER BY b | 劣 | a 範圍斷開,b 無序 |
WHERE a=10 AND b=10 ORDER BY c | 優 | a,b 皆常量,c 索引順序 |
WHERE a=10 AND b>10 ORDER BY c | 劣 | b 範圍斷開,c 無序 |
INT 優於 VARCHAR(255),減小索引體積、提高頁面密度。EXPLAIN 驗證 type=ref/range/index、Extra 無 Using filesort/Using temporary。# 快速檢查某 SQL 是否用到索引
mysql -uroot -p -e "EXPLAIN SELECT * FROM tbl WHERE a=1 ORDER BY b\G" | grep -E 'type|key|Extra'
複合索引不是「建了就有效」,**順序、方向、WHERE/Order By 協同**三位一體才能發揮威力。將上述速查表貼在工位,寫 SQL 時對照,索引失效率直降 80%。