Mysql官方對索引的定義是:索引(Index)是幫助Mysql高效獲取數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu)。
可以得到索引的本質(zhì):索引是一種數(shù)據(jù)結(jié)構(gòu)。
為什么要建索引?
索引的目的在于提高查詢效率。
比如:如果要查“mysql”這個單詞,我們肯定需要定位到m字母,然后從下往下找到y(tǒng)字母,再找到剩下的sql。
如果沒有索引,那么你可能需要a----z,會使查找效率變慢。
索引也可以理解為:排好序的快速查找數(shù)據(jù)結(jié)構(gòu)。
索引有兩大功能:查找快,排好序。也即建的索引將會影響到Sql的兩部分。
第一部分:就是where條件后面這部分的條件約束是否用到索引,這部分就是負責查找的條件過濾。
第二部分:索引會影響到where后面的查找以及order by后面的排序。
在數(shù)據(jù)本身之外,數(shù)據(jù)庫系統(tǒng)還維護著滿足特定查找算法的數(shù)據(jù)結(jié)構(gòu),這些數(shù)據(jù)結(jié)構(gòu)以某種方式引用(指向)數(shù)據(jù),這樣就可以在這些數(shù)據(jù)結(jié)構(gòu)上實現(xiàn)高級查找算法。這種數(shù)據(jù)結(jié)構(gòu),就是索引。下圖就是一種可能的索引方式示例:

索引的優(yōu)勢:
類似大學圖書館中建書目的索引,提高數(shù)據(jù)檢索的效率,降低了數(shù)據(jù)庫的IO成本。
通過對索引列對數(shù)據(jù)進行排序,降低數(shù)據(jù)排序的成本,降低了CPU的消耗。
索引的劣勢:
實際上索引也是一張表,該表保存了主鍵與索引的字段,并指向?qū)嶓w表的記錄,所以索引列也是要占用空間的。
雖然索引大大的提高了查詢的效率,同時卻會降低更新表的速度,如對表進行inser,update以及detele。因為更新表時,Mysql不僅要保存數(shù)據(jù),還要保存一下索引文件每次更新添加了索引列的字段,都會調(diào)整因為更新所帶來的鍵值變化后的索引信息。
索引只是提高查詢效率的一個因素,如果有大數(shù)據(jù)量的表,就需要花時間研究建立最優(yōu)秀的索引或優(yōu)化查詢語句。
索引分類和建索引語句:
1.單值索引:即一個索引只包含單個列,一個表可以有多個單列索引。
2.唯一索引:索引列的值必須唯一,但允許有空值。
3.復(fù)合索引:即一個索包含多個列。
基本的語句:
如果建的是唯一索引,那么就加UNIQUE這個關(guān)鍵字,不加就可以省略。
如果是CHAR VARCHAR類型,length可以小于字段的實際長度。如果是BLOB和TEXT類型,必須指定length。
如果columnname(length)寫了多個,那么就是復(fù)合索引。
第一種建法:
1.CREATE [UNIQUE] INDEX indexName ON mytable(columnname(length));//單值索引?
2.ALTER mytable ADD [UNIQUE] INDEX [indexName] ON (columnname(length))? //單值索引
刪除索引:
3.DROP INDEX [indexName]ON mytable;? //意思就是把某個表中的某個索引給刪了
查看索引:
4.SHOW INDEX FROM Table_name\G;

有四種方式來添加數(shù)據(jù)表的索引:
1.ALTER TABLE tbl_name ADD PRIMARY KEY (column_list): 該語句添加一個主鍵,這意味著索引值必須是唯一的,且不能為NULL。
2.ALTER TABLE tbl_name ADD UNIQUE index_name (column_list): 這條語句創(chuàng)建索引的值必須是唯一的(除了NULL外,NULL可能會出現(xiàn)多次)。
3.ALTER TABLE tbl_name ADD INDEX index_name (column_list): 添加普通索引,索引值可出現(xiàn)多次。
4.ALTER TABLE tbl_name ADD FULLTEXT index_name (column_list):該語句指定了索引為 FULLTEXT ,用于全文索引。
Java開發(fā)相關(guān)的Mysql索引結(jié)構(gòu):
BTree索引:

【初始化介紹】 一顆b+樹,淺藍色的塊我們稱之為一個磁盤塊,可以看到每個磁盤塊包含幾個數(shù)據(jù)項(深藍色所示)和指針(黃色所示),如磁盤塊1包含數(shù)據(jù)項17和35,包含指針P1、P2、P3,P1表示小于17的磁盤塊,P2表示在17和35之間的磁盤塊,P3表示大于35的磁盤塊。真實的數(shù)據(jù)存在于葉子節(jié)點即3、5、9、10、13、15、28、29、36、60、75、79、90、99。非葉子節(jié)點只不存儲真實的數(shù)據(jù),只存儲指引搜索方向的數(shù)據(jù)項,如17、35并不真實存在于數(shù)據(jù)表中。
【查找過程】如果要查找數(shù)據(jù)項29,那么首先會把磁盤塊1由磁盤加載到內(nèi)存,此時發(fā)生一次IO,在內(nèi)存中用二分查找確定29在17和35之間,鎖定磁盤塊1的P2指針,內(nèi)存時間因為非常短(相比磁盤的IO)可以忽略不計,通過磁盤塊1的P2指針的磁盤地址把磁盤塊3由磁盤加載到內(nèi)存,發(fā)生第二次IO,29在26和30之間,鎖定磁盤塊3的P2指針,通過指針加載磁盤塊8到內(nèi)存,發(fā)生第三次IO,同時內(nèi)存中做二分查找找到29,結(jié)束查詢,總計三次IO。
真實的情況是,3層的b+樹可以表示上百萬的數(shù)據(jù),如果上百萬的數(shù)據(jù)查找只需要三次IO,性能提高將是巨大的,如果沒有索引,每個數(shù)據(jù)項都要發(fā)生一次IO,那么總共需要百萬次的IO,顯然成本非常非常高。
以下索引了解即可。
Hash索引
full-text全文索引
R-Tree索引
哪些情況下適合建索引?
1.主鍵自動建立唯一索引。
2.頻繁作為查詢條件的字段應(yīng)該建索引。
3.查詢中與其他表關(guān)聯(lián)的字段,外鍵關(guān)系建立索引。
4.頻繁更新的字段不適合創(chuàng)建索引:因為每次更新不單單只是更新了記錄,還會更新索引,加重了IO負擔。
5.Where條件里用不到的字段不創(chuàng)建索引。
6.單鍵/組合索引的選擇問題(高并發(fā)下傾向創(chuàng)建組合索引)。
7.查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度。
8.查詢中統(tǒng)計或者分組字段。
哪些情況下不適合建索引?
1.表記錄太少。
2.經(jīng)常增刪改的表:提高了查詢效率,但是同時卻會降低了更新表的速度,如對表進行INSERT,UPDATE以及DELETE。因為更新表時,MySql不僅要保存數(shù)據(jù),還要保存索引文件。
3.數(shù)據(jù)重復(fù)并且分布平均的表字段,因此應(yīng)該只給最經(jīng)常查詢和最經(jīng)常排序的數(shù)據(jù)列建立索引,但如果某個數(shù)據(jù)列包含許多重復(fù)的內(nèi)容,為它建立索引就沒有太大的實際效果。