首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫

MySQL 索引入門超級教程:從 B+ 樹原理到實戰優化全景圖

     編輯:MySQL 資料庫相關知識

一、 索引是什麼?

索引是為特定列構建的**有序數據結構**(MySQL 默認 B+ 樹),將「全表掃描」的 O(N) 降為「樹高掃描」的 O(log N):**掃描 20 行定位原本需 2^20 行的數據**。

二、 EXPLAIN:優化的「聽診器」

EXPLAIN SELECT `birthday` FROM `user` WHERE `birthday` < '1990/2/2';

核心列解讀:

列含義優化關注點
type訪問類型從好到壞:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL。**至少達到 range,最好 ref/eq_ref**。
possible_keys理論可用索引為空說明無索引可用,需檢查 WHERE 條件列。
key實際使用索引NULL 表示全表掃描;PRIMARY 表示走主鍵。
key_len索引長度越短越好(不失精度前提下)。
ref配合 key 使用的列/常量const 表示常量匹配。
rows預估掃描行數**核心指標**,越小越快(InnoDB 不準但趨勢對)。
Extra額外資訊❌ Using filesort、Using temporary;✅ Using index(覆蓋索引)、Using where。

三、 索引類型全景

類型特點適用場景
PRIMARY KEY唯一、非空、單表唯一主鍵標識
UNIQUE唯一、允許 NULL(多個 NULL)業務唯一鍵(郵箱、身份證)
INDEX (NORMAL)允許重複、允許 NULL普通查詢加速
FULLTEXT全文檢索,僅 MyISAM/5.6+ InnoDB 支持,中文需分詞器文章搜索(生產建議用 Elasticsearch/Coreseek/Xunsearch)

四、 數據類型選擇原則(影響索引效能)

  1. 越小越好:INT(4B) < BIGINT(8B);CHAR 定長適合固定長度(MD5、UUID),VARCHAR 適合變長。
  2. 簡單越好:整數比較快於字符串;用 DATETIME 存時間,不用字符串;用 INT UNSIGNED 存 IP(INET_ATON/INET_NTOA)。
  3. 盡量 NOT NULL:NULL 增加優化器複雜度,統計資訊不準;用 0、空串、特殊值代替。

五、 組合索引與最左前綴原理

創建 INDEX idx_c1_c2 (c1, c2) 等價於擁有三個索引:

  • (c1, c2)
  • (c1)
  • 無 (c2)、(c2, c1)

規則:查詢必須從索引**最左列開始連續匹配**,遇到範圍查詢(>、LIKE %...)停止。

WHERE c1=1 AND c2=2      -- ✅ 用到 (c1,c2)
WHERE c1=1               -- ✅ 用到 (c1)
WHERE c2=2               -- ❌ 無法用到索引
WHERE c1>1 AND c2=2      -- ⚠️ 僅用到 (c1),c2 失效

六、 索引創建、查看、刪除、修改語法

操作語法
建表時創建CREATE TABLE t (id INT PRIMARY KEY, name VARCHAR(20), KEY idx_name(name));
事後添加 (ALTER)ALTER TABLE t ADD INDEX idx_name(name); / ADD UNIQUE uk_email(email); / ADD PRIMARY KEY(id);
CREATE INDEXCREATE INDEX idx_name ON t(name); / CREATE UNIQUE INDEX uk_email ON t(email);
查看SHOW INDEX FROM t \G;
刪除DROP INDEX idx_name ON t; / ALTER TABLE t DROP INDEX idx_name; / ALTER TABLE t DROP PRIMARY KEY;
修改**不支持直接修改**,刪除重建。

七、 索引設計六大技巧

  1. 高區分度列優先:count(DISTINCT col)/count(*) 越大越好。性別(0.5)不如年齡(高)。
  2. WHERE/ON/GROUP BY/ORDER BY 列建索引:這些是索引發揮作用的場景。
  3. 小列優先:索引文件更小,內存能裝更多鍵值。
  4. 長字符串用前綴索引:INDEX idx_title(title(10))。判斷標準:COUNT(DISTINCT LEFT(title,10))/COUNT(*) > 0.31(黃金分割點)。
  5. 不要過度索引:每增刪改一次重構索引,DML 性能下降。讀多寫少場景可接受。
  6. 組合索引優於多單列索引:文件更小,避免「索引合併」開銷,單遍掃描完成過濾+排序。

八、 什麼 SQL 不走索引?(避坑清單)

-- 1. 索引列參與計算
WHERE age + 10 = 30

-- 2. 索引列使用函數
WHERE LEFT(date_col, 4) < 1990
WHERE YEAR(create_time) = 2023

-- 3. LIKE 以通配符開頭
WHERE name LIKE '%keyword%'   -- 不走索引
WHERE name LIKE 'prefix%'     -- 走索引

-- 4. 正則表達式
WHERE name REGEXP 'pattern'

-- 5. 字符串與數字隱式轉換
CREATE TABLE a (a CHAR(10));
EXPLAIN SELECT * FROM a WHERE a = '1';  -- 走索引
EXPLAIN SELECT * FROM a WHERE a = 1;    -- ❌ 不走索引(隱式 CAST)

-- 6. OR 條件未全覆蓋索引
WHERE indexed_col = 1 OR non_indexed_col = 2  -- 全表掃描
-- 建議:拆分為 UNION ALL 或確保所有 OR 列都有索引

-- 7. 優化器判斷全表掃描更快
-- 小表、高選擇率、統計資訊過期等

九、 多表 JOIN 索引效能對比

JOIN索引對比圖

  • 無索引:全表掃描笛卡爾積,**6×6×6=216 次遍歷**。
  • 驅動表全掃描(必須),被驅動表走 range 索引:**6+1+1+1=9 次遍歷**。
  • 建議:少 JOIN、小表驅動大表、優先 LEFT JOIN、被驅動表關聯列必須有索引。

十、 索引的代價與權衡

  • ✅ **查詢快**(讀多寫少場景佔 80-90%)
  • ❌ **寫慢**:INSERT/UPDATE/DELETE 需維護索引樹
  • ❌ **佔空間**:每個索引一棵 B+ 樹
  • 大數據導入技巧:刪除索引 → 批量載入 → 重建索引,比邊導入邊維護快數量級。

十一、 總結

索引是 B+ 樹,核心在於**最左前綴**、**高區分度**、**覆蓋索引**、**避免函數/計算破壞順序**。用 EXPLAIN 看 type、key、rows、Extra。**優化不是加索引,而是「對的地方加對的索引」。**

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved