這個(gè)索引真的是面試必考題谁鳍,但是我也不知道面試官問這玩意有啥用,回答都是百度的,問一百個(gè)人倘潜,90個(gè)人回答的一樣绷柒,剩下是十個(gè)人是沒背下來。
而且背了容易忘涮因。我就是被了好幾遍都記不住废睦。
所以我決定看看索引到底是個(gè)什么東西,知道了原理养泡,也就很難忘記了嗜湃。
索引這個(gè)東西常見這幾種:
1.普通索引
2.唯一索引
3.主鍵索引
4.聯(lián)合索引
我們先來所以下主鍵索引是怎么搞的,其他索引類似澜掩。
這篇文章中講了在InnoDB的索引頁(yè)中是怎么根據(jù)主鍵查數(shù)據(jù)的购披。
但是問題是,索引頁(yè)多了怎么辦肩榕?
不還是要從第一個(gè)頁(yè)查起刚陡,一個(gè)一個(gè)去查。這樣有一萬(wàn)個(gè)頁(yè)株汉,不還是會(huì)有問題筐乳。
所以為了解決這個(gè)問題,新搞了一個(gè)一種記錄
之前record_type
就是記錄中表示記錄類型的地方乔妈。
0表示普通記錄
1目錄項(xiàng)記錄
2表示最小記錄
3表示最大記錄
因?yàn)轫?yè)內(nèi)蝙云,有槽作為目錄,可以使用二分法快速查詢褒翰,那頁(yè)我們也來搞一個(gè)目錄
下圖中的key
就是該頁(yè)最小索引值贮懈,page_no
就是頁(yè)號(hào)
這樣的話,如果我們?nèi)ゲ樗饕秊?的數(shù)據(jù)优训,就現(xiàn)在目錄中查朵你,知道了在28頁(yè),在用頁(yè)內(nèi)查詢辦法揣非,去查詢抡医。
但是這些目錄要存起來啊,所以就把這一條一條數(shù)據(jù)變成了一條目錄項(xiàng)記錄早敬,這條記錄的record_type
就是1
把這樣的多條數(shù)據(jù)放在一個(gè)頁(yè)中
就組成了這樣的一個(gè)東西忌傻。
數(shù)據(jù)量繼續(xù)增加,導(dǎo)致目錄項(xiàng)記錄的頁(yè)頁(yè)特別多搞监,那就意思類推水孩,在向上建立目錄項(xiàng)記錄頁(yè)。最后層層向上琐驴,最終形成如下
這就成了樹俘种,也就是B+樹秤标。
這些頁(yè),都統(tǒng)一稱作節(jié)點(diǎn)
最下層節(jié)點(diǎn)稱作葉子節(jié)點(diǎn)/葉節(jié)點(diǎn)
用來存放目錄項(xiàng)的節(jié)點(diǎn)成為非葉子節(jié)點(diǎn)/內(nèi)節(jié)點(diǎn)
最上層稱作根節(jié)點(diǎn)
所有葉子節(jié)點(diǎn)是存放用戶數(shù)據(jù)的
所有內(nèi)節(jié)點(diǎn)是存放目錄記錄數(shù)據(jù)的
有兩個(gè)特點(diǎn):
1.使用記錄主鍵值的大小進(jìn)行記錄和頁(yè)的排序宙刘,分為三方面
頁(yè)內(nèi)記錄是按照主鍵大小順序拍成一個(gè)單向鏈表
各個(gè)存放用戶記錄的頁(yè)也是根據(jù)頁(yè)中記錄的主鍵大小順序拍成的一個(gè)雙向鏈表
存放目錄記錄的頁(yè)苍姜,分為不同的層次,在同一層次悬包,也是按照記錄記錄的主鍵大小排序
2.葉子節(jié)點(diǎn)儲(chǔ)存的是完整的用戶記錄
具有這兩種特點(diǎn)的B+樹成為聚簇索引衙猪,這也是InnoDB中數(shù)據(jù)儲(chǔ)存的方式。
二級(jí)索引
上面說的只是主鍵索引布近,但是查別的時(shí)候不久不可以了嗎垫释?
所以按照別的列搜索怎么辦?
那就再栽一棵樹撑瞧。
這里的樹排序方式不是按照索引饶号,而是按照特定的列去排序。并且數(shù)據(jù)記錄中只有主鍵和索引值季蚂。
目錄記錄頁(yè)中的數(shù)據(jù)也是索引列和主鍵(主鍵的存在是為了唯一)
所以創(chuàng)建這樣一個(gè)樹之后茫船,在去按照該索引列查數(shù)據(jù)的時(shí)候,是先在這個(gè)樹中查出來主鍵扭屁,在去聚簇索引中根據(jù)主鍵查出所有數(shù)據(jù)算谈。
也就是說,這樣查了兩個(gè)樹料滥,第二次也被稱為回表
然眼。
聯(lián)合索引
有時(shí)候可能會(huì)有列1和列2進(jìn)行聯(lián)合索引
這樣就是在二級(jí)索引的基礎(chǔ)上加上一列。
排序方式是先按照列1進(jìn)行排序葵腹,有相同的在按照列2排序高每。
根節(jié)點(diǎn)
前面的敘述,感覺上像是先有的用戶記錄践宴,然后在向上產(chǎn)生內(nèi)節(jié)點(diǎn)鲸匿,根節(jié)點(diǎn)。但是事實(shí)不是這樣的阻肩。
首先一個(gè)表創(chuàng)刊一個(gè)B+樹索引的時(shí)候带欢,都會(huì)創(chuàng)建一個(gè)根節(jié)點(diǎn)。最開始啥都沒有烤惊,就是個(gè)空頁(yè)乔煞。
然后慢慢填充,一開始按照正常的頁(yè)去填充柒室,知道這個(gè)頁(yè)滿了渡贾。
如果在添加一條數(shù)據(jù),這個(gè)根節(jié)點(diǎn)的頁(yè)就會(huì)將所有的用戶記錄復(fù)制一份到新的頁(yè)雄右,然后進(jìn)行頁(yè)分裂(因?yàn)橐粋€(gè)頁(yè)不夠裝了)空骚。這時(shí)候根節(jié)點(diǎn)就會(huì)變成目錄記錄頁(yè)锦溪。
待目錄記錄頁(yè)裝滿之后,還會(huì)復(fù)制到新的頁(yè)中進(jìn)行頁(yè)分裂府怯,增加一個(gè)層級(jí)。
根節(jié)點(diǎn)的頁(yè)碼萬(wàn)年不變防楷。