當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]在InnoDB的數(shù)據(jù)頁(yè)到底長(zhǎng)什么樣?這篇文章里,我們講了InnoDB數(shù)據(jù)頁(yè)長(zhǎng)什么樣,簡(jiǎn)單回顧下。圖1?InnoDB數(shù)據(jù)頁(yè)結(jié)構(gòu)示意圖(圖片來(lái)自網(wǎng)絡(luò))其中有的部分沒(méi)有詳細(xì)講解,因?yàn)闀簳r(shí)還用不到。比如PageDirectory頁(yè)目錄。上面講了數(shù)據(jù)頁(yè)的內(nèi)部結(jié)構(gòu),數(shù)據(jù)庫(kù)最終所有的數(shù)據(jù)都是要...

在InnoDB的數(shù)據(jù)頁(yè)到底長(zhǎng)什么樣?這篇文章里,我們講了InnoDB數(shù)據(jù)頁(yè)長(zhǎng)什么樣,簡(jiǎn)單回顧下。

深入理解為什么MySQL全表掃描很慢?

圖1?InnoDB數(shù)據(jù)頁(yè)結(jié)構(gòu)示意圖(圖片來(lái)自網(wǎng)絡(luò))


其中有的部分沒(méi)有詳細(xì)講解,因?yàn)闀簳r(shí)還用不到。比如Page Directory頁(yè)目錄。


上面講了數(shù)據(jù)頁(yè)的內(nèi)部結(jié)構(gòu),數(shù)據(jù)庫(kù)最終所有的數(shù)據(jù)都是要放到磁盤上去的,那么大量的數(shù)據(jù)頁(yè)在磁盤上是怎么存儲(chǔ)的呢?其實(shí)數(shù)據(jù)頁(yè)之間會(huì)通過(guò)雙向鏈表連接起來(lái)。

深入理解為什么MySQL全表掃描很慢?

圖2 數(shù)據(jù)頁(yè)雙向鏈表連接起來(lái)


內(nèi)存中的雙向鏈表大家都能理解,那么磁盤上的雙向鏈表是怎么搞的呢?


其實(shí),數(shù)據(jù)頁(yè)在磁盤上就是一段數(shù)據(jù),里面包含的兩個(gè)指針,一個(gè)指向自己上一個(gè)數(shù)據(jù)頁(yè)的物理地址,一個(gè)指向下一個(gè)數(shù)據(jù)頁(yè)的物理地址。


每個(gè)數(shù)據(jù)頁(yè)內(nèi)部的User Records行記錄部分會(huì)存儲(chǔ)一行一行的數(shù)據(jù),這些行數(shù)據(jù)會(huì)按照逐漸的大小進(jìn)行排序存儲(chǔ),每一行數(shù)據(jù)都有一個(gè)指針指向下一行數(shù)據(jù)的位置,組成單向鏈表。

深入理解為什么MySQL全表掃描很慢?

圖3 數(shù)據(jù)頁(yè)在磁盤文件里的物理存儲(chǔ)結(jié)構(gòu)


數(shù)據(jù)頁(yè)的頁(yè)目錄是個(gè)重要的東西,目錄的作用就是方便檢索。這里的目錄,同樣有這樣的作用。


頁(yè)目錄里有很多個(gè)槽位(slots),這個(gè)槽位對(duì)應(yīng)一組數(shù)據(jù),可以理解為真實(shí)數(shù)據(jù)與頁(yè)面中第0個(gè)字節(jié)之間的偏移量。每個(gè)槽中,存放著每個(gè)組里最大的那條記錄所在頁(yè)面中的地址偏移量。


頁(yè)目錄就存放的是主鍵與槽位的映射關(guān)系,如圖:

深入理解為什么MySQL全表掃描很慢?

圖4?頁(yè)目錄


所以說(shuō),如果你要根據(jù)主鍵查找一條數(shù)據(jù),假設(shè)你表里沒(méi)幾條數(shù)據(jù),那個(gè)表就一個(gè)數(shù)據(jù)頁(yè),那就直接在數(shù)據(jù)頁(yè)里根據(jù)主鍵二分查找。


通過(guò)二分查找在目錄里迅速定位到逐漸對(duì)應(yīng)的數(shù)據(jù)在哪個(gè)槽位里,然后到那個(gè)槽位里去,遍歷槽位里的每一行數(shù)據(jù),就能找到那個(gè)主鍵對(duì)應(yīng)的數(shù)據(jù)了。


如果你沒(méi)辦法使用主鍵查詢,只能進(jìn)到數(shù)據(jù)頁(yè)里,逐條數(shù)據(jù)遍歷查找了。


如果數(shù)據(jù)頁(yè)里有很多的數(shù)據(jù)頁(yè),該如何查找呢?


假設(shè)你沒(méi)有建立任何索引,只能從第一個(gè)數(shù)據(jù)頁(yè)開始遍歷所有的數(shù)據(jù)頁(yè),從第一個(gè)數(shù)據(jù)頁(yè)開始,把每個(gè)數(shù)據(jù)也從磁盤加載到buffer pool的緩存頁(yè)里去。


如果你是根據(jù)主鍵查找,你可以在數(shù)據(jù)頁(yè)的頁(yè)目錄里二分查找,如果是根據(jù)其他字段查找,就需要在數(shù)據(jù)頁(yè)里順著單鏈表遍歷了。


這個(gè)過(guò)程,其實(shí)就是全表掃描!


你在沒(méi)有任何所以的時(shí)候,查找數(shù)據(jù)就是一個(gè)全表掃描的過(guò)程,就是根據(jù)雙向鏈表把磁盤上的數(shù)據(jù)頁(yè)加載到磁盤的緩存頁(yè)里去,然后在緩存頁(yè)內(nèi)部查找那條數(shù)據(jù)。


這個(gè)過(guò)程是非常滿的,所以說(shuō)當(dāng)數(shù)據(jù)量大的時(shí)候,全表掃描性能非常低,應(yīng)該盡量避免全表掃描。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
關(guān)閉
關(guān)閉