如何在數據庫中使用索引
多數數據庫,使用 B 樹(Balance Tree)的結構來保存索引。
www.2cto.com
B 樹,
最上層節點:根節點
最下層節點:葉子節點
兩者之間的節點:中間節點
B 樹,顯著特征:從根節點,到各個葉子節點的距離都是相等的。如此,檢索任何值時,都經過相同數目的節點。
[sql]
CREATE INDEX idx_lname_pinyin ON employee(lname_pinyin);
SHOW INDEX FROM employee\G
DROP INDEX idx_lname_pinyin ON employee;
伴隨主鍵的定義而創建的特別索引,被稱為:叢生索引(Clustered Index)
一個表,只有一個叢生索引。
普通的索引,在葉子節點中保存的是指向實際表的指針。
而,叢生索引,在葉子節點中保存的就是實際數據。
叢生索引,
不需要為保存索引,而使用專用的硬盤空間,節約資源
不需要檢查索引後,再訪問實際的表,提高了效率
創建叢生索引時,需要對表中數據進行排序,因此,在執行數據插入、更新、刪除等操作時,比普通索引慢。
復合索引
[sql]
CREATE INDEX idx_pinyin ON employee( lname_pinyin, fname_pinyin);
SHOW INDEX FROM employee\G
唯一性索引
使用 UNIQUE 關鍵字,來創建不可重復的索引,稱為:唯一性索引。
對特定列創建唯一性索引,相當於對該列追加了唯一性制約。
創建唯一性索引的時候,如果對象列中,已經含有重復數據,則:創建失敗,報錯。
創建成功後,如果,插入重復數據,則:插入失敗,報錯。
指定多個列,來創建唯一性索引,只要,這些列的組合數據不重復,就可以創建成功。
[sql]
CREATE UNIQUE INDEX idx_fname ON employee(fname);
CREATE UNIQUE INDEX idx_lname ON employee(lname);
CREATE UNIQUE INDEX idx_fullname ON employee(lname, fname);
[sql]
EXPLAIN SELECT * FROM employee WHERE lname_pinyin='wang'\G
[sql]
CREATE INDEX idx_lname_pinyin ON employee(lname_pinyin);
EXPLAIN SELECT * FROM employee WHERE lname_pinyin='wang'\G
EXPLAIN 命令的說明:P100 表格
如果,創建索引後,遍歷的次數與創建索引之前,變化不大。
說明,創建索引時,選擇的列名不合理,需要選擇合適的列重建索引。這是分析索引優劣的方法。
追加了索引後,也不能保證在每次檢索時都會使用列索引。
如果, SQL 檢索語句編寫不當,就無法使用索引。
1、LIKE 運算符,進行模糊檢索時,只能在前方一致的檢索時,才能使用索引。
以下寫法,索引不會被使用。
[sql]
SELECT * FROM employee WHERE lname_pinyin LIKE '%w%';
SELECT * FROM employee WHERE lname_pinyin LIKE '%w';
2、使用 IS NOT NULL 、 <> 的場合,也不會使用索引。如下:
[sql]
SELECT * FROM employee WHERE lname_pinyin IS NOT NULL;
SELECT * FROM employee WHERE lname_pinyin <> 'wang';
3、對列使用了運算或者函數的情況下,不會使用索引,如下:
[sql]
SELECT * FROM employee WHERE YEAR(birth) = '1980'; -- 不使用索引
SELECT * FROM employee WHERE birth >= '1980-01-01' AND birth <= '1980-12-31'; --使用了索引
4、復合索引的第一列,沒有包含在 WHERE 條件語句中,如下:
[sql]
CREATE INDEX idx_pinyin ON employee(lname_pinyin, fname_pinyin);
SELECT * FROM employee WHERE lname_pinyin = 'wang' AND fname_pinyin = 'xiao'; --用了索引
SELECT * FROM employee WHERE lname_pinyin = 'wang'; --用了索引
SELECT * FROM employee WHERE fname_pinyin = 'xiao'; -- 沒有使用索引
SELECT * FROM employee WHERE lname_pinyin = 'wang' OR fname_pinyin = 'xiao'; -- 沒有使用索引
實際開發過程中,需要積極使用 EXPLAIN 命令,來確認索引的使用情況,及時作相應修改。