無索引時,WHERE name='test' 需全表掃描,複雜度 O(N)。建立索引後,MySQL 以 B+ 樹預排序,複雜度降為 O(log N) 或 O(1)(唯一值),百萬級數據查詢從秒級降至毫秒級。
僅對以下操作符生效:<, <=, >, >=, =, BETWEEN, IN、LIKE 'prefix%'(不以通配符開頭)。
不生效:LIKE '%suffix'、LIKE '%mid%'、函數包裹列(UPPER(col)='A')、隱式類型轉換(字符列比數字)。
最基本,無唯一性限制。
-- 三種創建方式
CREATE INDEX idx_name ON tbl(col(len));
ALTER TABLE tbl ADD INDEX idx_name (col(len));
CREATE TABLE tbl (..., INDEX idx_name (col(len)));
CHAR/VARCHAR 可指定前綴長度 len(節省空間)。BLOB/TEXT 必須 指定前綴長度。值唯一,允許多個 NULL。
CREATE UNIQUE INDEX uk_email ON users(email);
ALTER TABLE users ADD UNIQUE uk_email (email);
CREATE TABLE users (..., UNIQUE uk_email (email));
特殊的唯一索引:不允許 NULL、一張表只能有一個、InnoDB 為聚簇索引(數據與索引同存)。
CREATE TABLE t (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(16) NOT NULL,
PRIMARY KEY (id)
);
常用 ALTER TABLE t ADD PRIMARY KEY (id) 補充。
MATCH(col) AGAINST('word')。CREATE TABLE articles (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(200),
body TEXT,
FULLTEXT (title, body)
) ENGINE=MyISAM;
SELECT * FROM articles
WHERE MATCH(title, body) AGAINST('database' IN NATURAL LANGUAGE MODE);
-- 布爾模式
SELECT * FROM articles
WHERE MATCH(title, body) AGAINST('+MySQL -YourSQL' IN BOOLEAN MODE);
組合索引 = 在已索引結果集上再索引,遵循最左前綴原則。
ALTER TABLE test ADD INDEX idx_combo (col1, col2, col3);
WHERE col1=1 AND col2=2 → 用到索引。WHERE col2=2 → 不用(未包含最左列)。WHERE col1=1 AND col3=3 → 僅用到 col1。COUNT(DISTINCT col)/COUNT(*) 越接近 1 越適合做索引首列。>, <, LIKE '%...')後的列失效。Using index)。| 場景 | 原因 | 修正 |
|---|---|---|
WHERE col + 1 = 2 | 列運算導致隱式轉換 | WHERE col = 1 |
WHERE VARCHAR_col = 123 | 字符列比數字,隱式轉換 | WHERE VARCHAR_col = '123' |
WHERE UPPER(name) = 'A' | 函數破壞索引 | 功能性索引(8.0+)或冗余列存大寫 |
WHERE col LIKE '%abc' | 前導通配符 | 全文索引/反轉存儲/應用層過濾 |
組合索引 (a,b,c),查 WHERE b=1 | 非最左前綴 | 調整索引順序或建單列索引 |
WHERE a=1 AND b>2 AND c=3 索引 (a,b,c) | 範圍列 b 後的 c 失效 | 索引 (a,c,b) 或接受 c 不走索引 |
ORDER BY b DESC 索引 (a ASC, b ASC) | 排序方向不一致 | 索引 (a ASC, b DESC) (8.0+) |
索引是查詢性能的杠桿,但也是寫入性能的負擔。掌握B+ 樹原理、最左前綴、覆蓋索引、範圍列陷阱四大核心,結合 EXPLAIN 實測驗證,才能做出精準的索引決策。