什么是索引
?對(duì)于業(yè)務(wù)系統(tǒng),我們一般的更新操作要比查詢操作少的多。對(duì)于系統(tǒng)經(jīng)常優(yōu)化的點(diǎn)也就是查詢操作,因?yàn)樵诓樵兊臅r(shí)候很浪費(fèi)時(shí)間因俐,有的查詢就是全表掃描,查詢時(shí)間就特別的慢找蜜。這個(gè)時(shí)候我們就要考慮索引腥例,索引可以大大加快我們的查詢速度。
為什么要用索引
?對(duì)于大量的查詢子姜,有了索引可以將查詢的性能提高好幾個(gè)等級(jí)祟绊。比如我們?cè)趫D書館找書一樣,我們先找到該圖書的樓層,再找到圖書的分類編碼牧抽,最后找到圖書嘉熊。這樣找圖書就和索引找數(shù)據(jù)是一樣的道理。
索引的原理
基本原理
?通過縮小我們查詢范圍來篩選出我們想要的結(jié)果扬舒。同時(shí)把隨機(jī)時(shí)間變成順序事件阐肤,也就是說有了這種索引機(jī)制,我們總是可以用同一種方式來查找數(shù)據(jù)讲坎。就像圖書館找書一樣孕惜,我們可以把找書的原理適用于任何的查找。
?數(shù)據(jù)庫也是一樣的晨炕。但是這里的查詢要復(fù)雜的多衫画,這里不僅面臨等值查詢,還有范圍查詢(between瓮栗、or削罩、and、in遵馆、>鲸郊、<等)、模糊查詢(like)等等货邓。數(shù)據(jù)庫對(duì)于這些的查詢應(yīng)該怎么做到查詢的速度快秆撮?我來回想之前的圖書查找,我們把圖書查找聯(lián)想到新華字典的查找换况,新華字典將字按照首字母進(jìn)行分割职辨。我們也可以考慮將查詢的數(shù)據(jù)進(jìn)行分割,比如現(xiàn)在有1000條數(shù)據(jù)戈二,我們分成十份舒裤,1-100分下去。現(xiàn)在我們要查找33觉吭,這個(gè)數(shù)據(jù)就是在1-100之間我們直接去從查找腾供,直接過濾掉一些不符合規(guī)則的數(shù)據(jù)。但是數(shù)據(jù)庫的實(shí)現(xiàn)一方面將數(shù)據(jù)是保存在磁盤上的鲜滩,另外一方面為了提高性能伴鳖,每次又可以把部分?jǐn)?shù)據(jù)讀入內(nèi)存來計(jì)算,因?yàn)槲覀冎涝L問磁盤的成本要比訪問內(nèi)存高得多徙硅。我們說的上面的思路是難以實(shí)現(xiàn)的榜聂。
索引的數(shù)據(jù)結(jié)構(gòu)
?上面圖所畫結(jié)構(gòu)就是索引的數(shù)據(jù)結(jié)構(gòu)圖(B+樹),淺藍(lán)色代表磁盤嗓蘑,紅色代表是數(shù)據(jù)項(xiàng)须肆,黃色代表指針匿乃。真實(shí)的數(shù)據(jù)這存在葉節(jié)點(diǎn)(最底層)。例如我們的1,3,9,10,14,18,25,38,45,50,60,80,101,123豌汇。非葉子節(jié)點(diǎn)只存指引搜索方向的數(shù)據(jù)項(xiàng)幢炸。
?B+樹的查找過程:比如現(xiàn)在我們查找數(shù)據(jù)項(xiàng)14,首先我們將磁盤1加載到內(nèi)存中瘤礁,這是發(fā)生第一次IO阳懂,在內(nèi)存中利用二分查找法找到數(shù)據(jù)項(xiàng)14在小于15的區(qū)間,這是鎖定磁盤1的P1指針柜思,這個(gè)操作在內(nèi)存中發(fā)生可以忽略不計(jì)岩调。這個(gè)時(shí)候我們通過P1指針將磁盤2加載到內(nèi)存中,這是又發(fā)生了第二次IO赡盘。我們?cè)趦?nèi)存通過二分查找算法找到數(shù)據(jù)項(xiàng)14在大于13的區(qū)間号枕,這是通過磁盤2的指針P3指向?qū)⒋疟P7加載到內(nèi)存當(dāng)中,發(fā)生了第三次IO陨享,這個(gè)時(shí)候通過二分查找就找到了數(shù)據(jù)項(xiàng)14葱淳。我們只通過了產(chǎn)生三次IO就找到了數(shù)據(jù),如果沒有索引的話抛姑,每個(gè)數(shù)據(jù)項(xiàng)的都要差生一次IO赞厕,顯然查詢的速度很慢、成本也好高定硝。
B+樹的性質(zhì)
?索引的字段要盡量小:通過上面的分析皿桑,我們知道的IO的次數(shù)取決于樹的高度。數(shù)據(jù)量的大小 = 磁盤塊的大小 / 數(shù)據(jù)項(xiàng)的大小蔬啡,磁盤塊的大小也就是一個(gè)數(shù)據(jù)頁的大小诲侮,是固定的,如果數(shù)據(jù)項(xiàng)占的空間越小箱蟆,數(shù)據(jù)項(xiàng)的數(shù)量越多沟绪,樹的高度越低。這就是為什么每個(gè)數(shù)據(jù)項(xiàng)空猜,即索引字段要盡量的小绽慈,比如int占4字節(jié),要比bigint8字節(jié)少一半辈毯。這也是為什么b+樹要求把真實(shí)的數(shù)據(jù)放到葉子節(jié)點(diǎn)而不是內(nèi)層節(jié)點(diǎn)久信,一旦放到內(nèi)層節(jié)點(diǎn),磁盤塊的數(shù)據(jù)項(xiàng)會(huì)大幅度下降漓摩,導(dǎo)致樹增高。當(dāng)數(shù)據(jù)項(xiàng)等于1時(shí)將會(huì)退化成線性表入客。
?索引的最左匹配特性:當(dāng)b+樹的數(shù)據(jù)項(xiàng)是復(fù)合的數(shù)據(jù)結(jié)構(gòu)管毙,比如(name,age,sex)的時(shí)候腿椎,b+數(shù)是按照從左到右的順序來建立搜索樹的,比如當(dāng)(張三,20,F)這樣的數(shù)據(jù)來檢索的時(shí)候夭咬,b+樹會(huì)優(yōu)先比較name來確定下一步的所搜方向啃炸,如果name相同再依次比較age和sex,最后得到檢索的數(shù)據(jù)卓舵;但當(dāng)(20,F)這樣的沒有name的數(shù)據(jù)來的時(shí)候南用,b+樹就不知道下一步該查哪個(gè)節(jié)點(diǎn),因?yàn)榻⑺阉鳂涞臅r(shí)候name就是第一個(gè)比較因子掏湾,必須要先根據(jù)name來搜索才能知道下一步去哪里查詢裹虫。比如當(dāng)(張三,F)這樣的數(shù)據(jù)來檢索時(shí),b+樹可以用name來指定搜索方向融击,但下一個(gè)字段age的缺失筑公,所以只能把名字等于張三的數(shù)據(jù)都找到,然后再匹配性別是F的數(shù)據(jù)了尊浪, 這個(gè)是非常重要的性質(zhì)匣屡,即索引的最左匹配特性。
索引分類
?普通索引:加快查詢的速度
?唯一索引
??主鍵索引:primaryKey 索引+約束(不能為空并且唯一)
??唯一索引:unique 索引+約束(唯一)
?聯(lián)合索引:
??普通聯(lián)合索引:index(id拇涤,username)
??唯一聯(lián)合索引:unique(id捣作,username)
??主鍵聯(lián)合索引:primary key(id,username)
索引優(yōu)化
?1鹅士、不在索引上做任何操作(計(jì)算券躁、類型轉(zhuǎn)換、函數(shù))如绸,會(huì)導(dǎo)致索引失效而轉(zhuǎn)向全表的掃描嘱朽;
?2、Mysql在使用不等于的時(shí)候無法使用索引會(huì)導(dǎo)致全表的掃描怔接;
?3搪泳、like以通配符“%”開頭也會(huì)導(dǎo)致索引失效會(huì)變成全表的掃描;
?4扼脐、字符串不加單引號(hào)索引失效岸军;
?5、少用or來連接瓦侮,這樣也會(huì)是索引失效艰赞;
?6、最佳左前綴法則肚吏,我們的聯(lián)合索引必須按照從左到右的順序方妖,中間不能有斷裂否則索引失效;
?7罚攀、union or in 都能命中索引的時(shí)候党觅,盡量使用in雌澄;
?8、更新十分頻繁杯瞻、數(shù)據(jù)區(qū)分度不高的字段上不宜建立索引镐牺;
?9、建立索引的列魁莉,不允許為 null睬涧;
?10、單表索引建議控制在5個(gè)以內(nèi)旗唁;
?11畦浓、單索引字段數(shù)不允許超過5個(gè);
?12逆皮、創(chuàng)建索引時(shí)避免以下錯(cuò)誤觀念:
??* 索引越多越好宅粥,認(rèn)為一個(gè)查詢就需要建一個(gè)索引。
??* 寧缺勿濫电谣,認(rèn)為索引會(huì)消耗空間秽梅、嚴(yán)重拖慢更新和新增速度。
??* 抵制唯一索引剿牺,認(rèn)為業(yè)務(wù)的唯一性一律需要在應(yīng)用層通過“先查后插”方式解決企垦。
??* 過早優(yōu)化,在不了解系統(tǒng)的情況下就開始優(yōu)化晒来。