關係數據庫邏輯上是集合運算,但物理執行受限於 I/O、CPU、內存。全表掃描隨數據量線性增長,而索引通過有序數據結構 (B+Tree) 將查找複雜度降為 O(log N)。MySQL 郵件列表中 80% 以上的「查詢慢」問題,加上合適索引即可立竿見影解決。
表是無序堆,查找 company_num=13 需逐行比對,100 萬行需 100 萬次 I/O。
索引文件按 company_num 排序,包含 (鍵值, 行指針) 對。查找 13:
優勢:跳過 99% 無關行;支持 ORDER BY、MIN/MAX、覆蓋索引掃描等額外優化。
三表 t1/t2/t3 各 1000 行,無索引 JOIN 需 10 億次比較;有索引時:掃描 t1 (1000) → 索引查找 t2/t3 (各 1 次 I/O) → 總成本 ~3000,提速百萬倍。
| 維度 | 影響 | 應對策略 |
|---|---|---|
| 寫入性能 | INSERT/UPDATE/DELETE 需維護索引樹 | 僅建立必要索引;批量導入時先Drop索引後重建 |
| 存儲空間 | 每個索引佔用額外磁盤/內存 | 定期 ANALYZE TABLE 檢查索引大小;刪除未用索引 |
| 優化器誤判 | 統計信息過期導致錯誤選擇索引 | ANALYZE TABLE 更新統計;必要時 FORCE INDEX |
long_query_time=1),收集 Top 20 SQL;COUNT(DISTINCT col)/COUNT(*) 越接近 1 越適合建索引;INDEX (a,b,c) 支持 a、a,b、a,b,c 查詢;SELECT a,b FROM t WHERE c=1 → INDEX (c,a,b) 避免回表;EXPLAIN 觀察 type、key、rows、Extra (Using index/Using where/Using filesort);WHERE col + 1 = 10 / WHERE UPPER(name) = 'ABC' → 函數/運算作用於索引列;WHERE name LIKE '%abc' → 導模糊匹配無法利用 B+Tree 有序性;WHERE a=1 OR b=2 (無聯合索引) → 優化器傾向全表掃描;VARCHAR 列比較數字 WHERE phone=13800000000;INDEX(a,b,c) 查 WHERE b=1 或 WHERE a=1 AND c=2。-- 查看索引基數 (選擇性)
SHOW INDEX FROM tbl_name;
-- 查看實際使用情況 (5.6+ performance_schema)
SELECT * FROM sys.schema_unused_indexes; -- 未用索引
SELECT * FROM sys.schema_redundant_indexes; -- 冗余索引
索引是數據庫性能的杠桿,但非無成本。「測量 → 分析 → 設計 → 驗證 → 迭代」閉環,結合 EXPLAIN、慢查詢日志、performance_schema 系統表,才能在讀寫平衡點上構建最優索引集合。先加索引,再調 SQL,最後調架構,是性能優化的鐵律。