一、SQL索引基礎(chǔ):數(shù)據(jù)庫(kù)的“目錄”系統(tǒng)
1.1 為什么需要SQL索引?
想象一本500頁(yè)的《現(xiàn)代漢語(yǔ)詞典》:
- 沒(méi)有目錄:要查“數(shù)據(jù)庫(kù)”一詞,需逐頁(yè)翻閱(全表掃描)
- 有目錄:先查“數(shù)”字起始頁(yè)(索引檢索),快速定位
當(dāng)數(shù)據(jù)量達(dá)到百萬(wàn)級(jí)時(shí),SQL索引可將查詢速度提升幾十到幾百倍。
1.2 創(chuàng)建SQL索引的三種方式
-- 方式1:直接創(chuàng)建
CREATE INDEX idx_name ON users(email);
-- 方式2:修改表結(jié)構(gòu)
ALTER TABLE users ADD INDEX idx_name (email);
-- 方式3:建表時(shí)創(chuàng)建
CREATE TABLE users (
id INT PRIMARY KEY,
email VARCHAR(100),
INDEX idx_email (email) -- 普通索引
);
1.3 SQL索引管理命令
| | |
---|
| SHOW INDEX FROM users; | |
| DROP INDEX idx_email ON users; |
|
| SELECT ... FORCE INDEX(idx_name) | 優(yōu)化器選錯(cuò)索引時(shí)使用 |
二、SQL索引類型詳解:數(shù)據(jù)庫(kù)的“多重目錄”
2.1 按數(shù)據(jù)結(jié)構(gòu)劃分(存儲(chǔ)引擎層實(shí)現(xiàn))
?? 重點(diǎn)對(duì)比:
-- B+樹(shù)索引支持的操作
SELECT * FROM users WHERE age > 25; -- 范圍查詢
SELECT * FROM users ORDER BY create_time; -- 排序
-- 哈希索引僅支持
SELECT * FROM users WHERE id = 10086; -- 精確匹配
2.2 按字段數(shù)量劃分
| | |
---|
單列索引 | | INDEX (email) |
聯(lián)合索引 | | INDEX (last_name, first_name) |
?? 聯(lián)合索引最左前綴原則:
CREATE INDEX idx_name_phone ON users(last_name, phone);
-- ? 生效場(chǎng)景
SELECT * FROM users WHERE last_name = '張';
SELECT * FROM users WHERE last_name = '張' AND phone='138****8000';
-- ? 失效場(chǎng)景
SELECT * FROM users WHERE phone = '138****8000';
2.3 按功能邏輯劃分(最常用分類)
| | |
---|
普通索引 | | ADD INDEX idx_name (name) |
唯一索引 | | ADD UNIQUE INDEX (email) |
主鍵索引 | | ADD PRIMARY KEY (id) |
全文索引 | | ADD FULLTEXT INDEX (content) |
空間索引 | | ADD SPATIAL INDEX (geom) |
主鍵索引 vs 唯一索引:
INSERT INTO users (id, email) VALUES (NULL, 'a@test.com');
-- 主鍵索引報(bào)錯(cuò):主鍵不能為NULL
-- 唯一索引允許:唯一索引列允許一個(gè)NULL值
2.4 按存儲(chǔ)方式劃分(InnoDB核心機(jī)制)
| | |
---|
聚簇索引 | 索引節(jié)點(diǎn)直接包含行數(shù)據(jù) | |
非聚簇索引 | 存儲(chǔ)主鍵ID,需回表查詢數(shù)據(jù) | |
理解聚簇索引: 假設(shè)用戶表結(jié)構(gòu):
聚簇索引(主鍵索引):
- 葉子節(jié)點(diǎn)存儲(chǔ):| id | name | email | age |
非聚簇索引(普通索引):
- 葉子節(jié)點(diǎn)存儲(chǔ):| age | id |
當(dāng)通過(guò)非聚簇索引查詢時(shí):
SELECT name FROM users WHERE age = 30;
執(zhí)行路徑:age索引 -> 主鍵id -> 聚簇索引 -> 獲取數(shù)據(jù)行
三、模擬數(shù)據(jù)與應(yīng)用示例(10萬(wàn)行數(shù)據(jù)演示)
3.1 數(shù)據(jù)準(zhǔn)備
CREATE TABLE products (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(200) NOT NULL,
price DECIMAL(10,2) NOT NULL,
category VARCHAR(50) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB;
-- 插入10萬(wàn)條產(chǎn)品數(shù)據(jù)(腳本略)
3.2 SQL索引效果對(duì)比實(shí)驗(yàn)
場(chǎng)景1:無(wú)索引基礎(chǔ)查詢
-- 耗時(shí)約350ms
SELECT * FROM products WHERE category = 'electronics';
場(chǎng)景2:創(chuàng)建單列索引后
CREATE INDEX idx_category ON products(category);
-- 耗時(shí)降至8ms (提升44倍)
EXPLAIN SELECT * FROM products WHERE category='electronics';
-- 執(zhí)行計(jì)劃:type=ref, key=idx_category
場(chǎng)景3:聯(lián)合索引范圍查詢
CREATE INDEX idx_category_price ON products(category, price);
-- ? 高效查詢(使用索引)
SELECT * FROM products
WHERE category='books' AND price > 100;
-- ? 低效查詢(未用索引)
SELECT * FROM products WHERE price > 100;
場(chǎng)景4:覆蓋索引優(yōu)化
-- 原始查詢(需回表)
SELECT id, name FROM products WHERE category='furniture';
-- 創(chuàng)建覆蓋索引
CREATE INDEX idx_cover ON products(category, name, id);
-- 執(zhí)行計(jì)劃顯示"Using index"
EXPLAIN SELECT id, name FROM products WHERE category='furniture';
四、SQL索引使用注意事項(xiàng)
4.1 SQL索引的代價(jià)
4.2 SQL索引失效的六大場(chǎng)景
函數(shù)操作:
SELECT * FROM users WHERE UPPER(name) = 'JOHN'; -- 失效
SELECT * FROM users WHERE name = 'John'; -- 有效
隱式類型轉(zhuǎn)換:
-- phone是字符串類型
SELECT * FROM users WHERE phone = 13800138000; -- 失效
模糊查詢通配符開(kāi)頭:
SELECT * FROM users WHERE name LIKE '%son'; -- 失效
SELECT * FROM users WHERE name LIKE 'Joh%'; -- 有效
OR連接非索引列:
-- age列無(wú)索引
SELECT * FROM users WHERE name='John' OR age=30; -- 失效
聯(lián)合索引跳過(guò)首列:
CREATE INDEX idx_name_phone ON users(name, phone);
SELECT * FROM users WHERE phone='13800138000'; -- 失效
數(shù)據(jù)傾斜優(yōu)化器棄用:
-- 90%數(shù)據(jù)category='electronics'
SELECT * FROM products WHERE category='electronics'; -- 可能全表掃描
4.3 SQL索引設(shè)計(jì)原則
- 高頻查詢優(yōu)先:WHERE/JOIN/ORDER BY/GROUP BY涉及的列
- 區(qū)分度高原則:選Cardinality值高的列(如身份證號(hào)比性別適合)
- 控制索引數(shù)量:建議單表索引不超過(guò)5個(gè)
- 避免冗余索引:
INDEX(a,b) -- 已存在
INDEX(a) -- 冗余!
附錄:SQL索引學(xué)習(xí)地圖
graph TD
A[索引基礎(chǔ)] --> B[創(chuàng)建與管理]
A --> C[類型體系]
C --> D[數(shù)據(jù)結(jié)構(gòu)]
C --> E[字段數(shù)量]
C --> F[功能邏輯]
C --> G[存儲(chǔ)方式]
D --> H[B+樹(shù) vs 哈希]
E --> I[聯(lián)合索引最左前綴]
F --> J[主鍵/唯一/全文]
G --> K[聚簇/非聚簇]
L[實(shí)戰(zhàn)應(yīng)用] --> M[性能對(duì)比]
L --> N[覆蓋索引]
L --> O[失效場(chǎng)景]
閱讀原文:原文鏈接
該文章在 2025/9/1 12:07:06 編輯過(guò)