InnoDB存儲結(jié)構(gòu)與索引


title: InnoDB存儲結(jié)構(gòu)與索引
date: 2020-01-14 20:39:13
categories: 數(shù)據(jù)庫
tags:
- mysql
- 索引
- B+樹
description: InnoDB是一個(gè)將表中的數(shù)據(jù)存儲到磁盤上的存儲引擎


InnoDB將數(shù)據(jù)劃分為若干個(gè)頁梧奢,以頁作為磁盤和內(nèi)存之間交互的基本單位,InnoDB中頁的大小一般為 16 KB符欠。也就是在一般情況下希柿,一次最少從磁盤中讀取16KB的內(nèi)容到內(nèi)存中养筒,一次最少把內(nèi)存中的16KB內(nèi)容刷新到磁盤中挤悉。

行格式

InnoDB存儲引擎到現(xiàn)在為止設(shè)計(jì)了4種不同類型的行格式装悲,分別是Compact尚氛、Redundant阅嘶、Dynamic和Compressed行格式抡蛙。

  • 指定行格式
    CREATE TABLE 表名 (列的信息) ROW_FORMAT=行格式名稱
    ALTER TABLE 表名 ROW_FORMAT=行格式名稱

Compact行格式

-----------------------------------------------------------------------------
| 變長字段長度列表 | NULL值列表 | 記錄頭信息 | 列1的值 | 列2的值 |.....| 列n的值 |
-----------------------------------------------------------------------------
  1. 變長字段長度列表: 對于比如varchar類型可變長度的字段粗截,存儲的時(shí)候是不固定的慈格,因此需要根據(jù)實(shí)際的值來計(jì)算出實(shí)際字段長度遥金,保存到該列表

頁數(shù)據(jù)結(jié)構(gòu)

使用記錄和槽的方式存儲數(shù)據(jù)稿械,

名稱 解釋 占用空間大小 描述
File Header 文件頭部 38字節(jié) 頁的通用信息选泻,比如上一個(gè)頁信息梯捕、下一個(gè)頁
Page Header 頁頭部 56字節(jié) 數(shù)據(jù)頁的專有信息傀顾,比如槽的數(shù)量短曾,記錄的數(shù)量
Infimum+Superemum 最小記錄和最大記錄 26字節(jié) 兩個(gè)特殊的固定的記錄
User Records 用戶記錄 不定 實(shí)際存儲的行記錄
Free Space 尚未使用的空間 不定 尚未使用的
Page Directory 頁目錄 不定 頁中記錄的相對記錄嫉拐,也就是槽記錄的頁中每組最后一條記錄記錄的位置
File Trailer 文件尾部 8字節(jié) 校驗(yàn)頁的完整性

要點(diǎn):

  • 每個(gè)記錄的頭信息都有一個(gè)next_record的信息婉徘,從而形成單鏈表
  • InnoDB會把頁記錄劃分為若干個(gè)組,每個(gè)組的最后一個(gè)記錄的地址偏移量為一個(gè)槽咐汞,存放在Page Directory中盖呼,所以查找非常快
    1. 通過二分法確定該記錄所在的槽
    2. 通過記錄的next_record屬性遍歷該槽所在的組的各個(gè)記錄(每個(gè)組只有4-5條記錄)
  • 每個(gè)數(shù)據(jù)頁的File Header部分都有上一個(gè)和下一個(gè)頁的編號化撕,形成了一個(gè)雙鏈表
  • 為保證從內(nèi)存中同步到磁盤的頁的完整性塌计,在頁的首部和尾部都會存儲數(shù)據(jù)的校驗(yàn),和最后修改時(shí)對應(yīng)的LSN值

B+樹索引

在引入索引之前侯谁,如果通過主鍵查找,則可以通過二分法快速定位到相應(yīng)的的槽章钾,再依次遍歷單鏈表即可找到記錄墙贱,但如果是其他字段則沒有槽,需要遍歷數(shù)據(jù)頁的所有記錄贱傀,非常耗時(shí)

不論是根據(jù)主鍵列或者其他列的值進(jìn)行查找惨撇,由于我們并不能快速的定位到記錄所在的頁

問題一: 快速定位所在頁

  1. 保證,下一個(gè)頁的主鍵值大于上一個(gè)頁中用戶所有的主鍵值,所以在增刪改查的時(shí)候會有一些記錄移動的操作,這個(gè)過程叫做頁分裂

  2. 由于頁并不是連續(xù)的碰煌,所以需要建立一個(gè)頁目錄俄认,頁中最小主鍵值與頁號對應(yīng)。(這個(gè)目錄就是叫做索引)

    • 由于在數(shù)據(jù)量大的時(shí)候無法保證頁目錄連續(xù),也就是看做無法用數(shù)組存儲,所以采用存儲數(shù)據(jù)的方式存儲索引,這就是目錄項(xiàng)記錄頁,只不過record_type屬性不一樣妓湘,這里是1唬党,而普通記錄的頁中是0
    • 如果數(shù)據(jù)更大屯烦,那么目錄項(xiàng)記錄頁就可以再進(jìn)行壓縮,變成更高曾記得目錄項(xiàng)記錄頁,也就有了如下的結(jié)構(gòu):

這就是B+樹,以前一直不知道為什么只有葉子節(jié)點(diǎn)才存儲數(shù)據(jù),現(xiàn)在就非常清晰了纺涤,他們的record_type是不一樣的拧咳!

聚簇索引

我們上邊介紹的B+樹本身就是一個(gè)目錄谭网,或者說本身就是一個(gè)索引。它有兩個(gè)特點(diǎn):

  1. 使用記錄主鍵值的大小進(jìn)行記錄和頁的排序殖妇,這包括三個(gè)方面的含義:

    • 頁內(nèi)的記錄是按照主鍵的大小順序排成一個(gè)單向鏈表。

    • 各個(gè)存放用戶記錄的頁也是根據(jù)頁中用戶記錄的主鍵大小順序排成一個(gè)雙向鏈表。

    • 存放目錄項(xiàng)記錄的頁分為不同的層次,在同一層次中的頁也是根據(jù)頁中目錄項(xiàng)記錄的主鍵大小順序排成一個(gè)雙向鏈表治笨。

  2. B+樹的葉子節(jié)點(diǎn)存儲的是完整的用戶記錄探膊。

這種聚簇索引并不需要我們在MySQL語句中顯式的使用INDEX語句去創(chuàng)建(后邊會介紹索引相關(guān)的語句)绳瘟,InnoDB存儲引擎會自動的為我們創(chuàng)建聚簇索引

二級索引

上邊介紹的聚簇索引只能在搜索條件是主鍵值時(shí)才能發(fā)揮作用,因?yàn)锽+樹中的數(shù)據(jù)都是按照主鍵進(jìn)行排序的嘲玫。那如果我們想以別的列作為搜索條件該咋辦呢穷蛹?難道只能從頭到尾沿著鏈表依次遍歷記錄么?

不,我們可以多建幾棵B+樹出刷,不同的B+樹中的數(shù)據(jù)采用不同的排序規(guī)則改抡。比方說我們用c2列的大小作為數(shù)據(jù)頁、頁中記錄的排序規(guī)則荆忍,再建一棵B+樹,效果如下圖所示:

[圖片上傳失敗...(image-e59db8-1614334697826)]

注意與主鍵的聚簇索引有3點(diǎn)不同:

  1. 頁內(nèi)記錄都是按照c2來排列
  2. B+樹的葉子節(jié)點(diǎn)存儲的不是完整的用戶記錄钟鸵,而只是c2+主鍵這兩個(gè)列的值
  3. 目錄項(xiàng)記錄中不再是主鍵+頁號钉稍,而是c2+頁號

所以查找過程也與主鍵查找方式不同,我們是先通過索引建立的B+樹找到主鍵值棺耍,再通過主鍵找到對應(yīng)的完整記錄贡未,這個(gè)過程稱為回表,也就是根據(jù)c2列需要用到2棵B+樹

聯(lián)合索引

我們也可以同時(shí)以多個(gè)列的大小作為排序規(guī)則蒙袍,也就是同時(shí)為多個(gè)列建立索引俊卤,比方說我們想讓B+樹按照c2和c3列的大小進(jìn)行排序,這個(gè)包含兩層含義:

  • 先把各個(gè)記錄和頁按照c2列進(jìn)行排序害幅。
  • 在記錄的c2列相同的情況下消恍,采用c3列進(jìn)行排序

不同之處與二級索引類似,注意以现,之前我們常常提到的最左匹配就是這個(gè)原理狠怨,先比較c2,再比較c3邑遏,如果沒有c2佣赖,那么索引失效

注意構(gòu)建B+樹過程,根節(jié)點(diǎn)一直不變

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末记盒,一起剝皮案震驚了整個(gè)濱河市憎蛤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌孽鸡,老刑警劉巖蹂午,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異彬碱,居然都是意外死亡豆胸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門巷疼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晚胡,“玉大人,你說我怎么就攤上這事嚼沿」琅蹋” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵骡尽,是天一觀的道長遣妥。 經(jīng)常有香客問我,道長攀细,這世上最難降的妖魔是什么箫踩? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任爱态,我火速辦了婚禮,結(jié)果婚禮上境钟,老公的妹妹穿的比我還像新娘锦担。我一直安慰自己,他們只是感情好慨削,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布洞渔。 她就那樣靜靜地躺著,像睡著了一般缚态。 火紅的嫁衣襯著肌膚如雪磁椒。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天猿规,我揣著相機(jī)與錄音衷快,去河邊找鬼。 笑死姨俩,一個(gè)胖子當(dāng)著我的面吹牛蘸拔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播环葵,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼调窍,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了张遭?” 一聲冷哼從身側(cè)響起邓萨,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎菊卷,沒想到半個(gè)月后缔恳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡洁闰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年歉甚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扑眉。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡纸泄,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出腰素,到底是詐尸還是另有隱情聘裁,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布弓千,位于F島的核電站衡便,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜镣陕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一征唬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茁彭,春花似錦、人聲如沸扶歪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽善镰。三九已至妹萨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炫欺,已是汗流浹背乎完。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留品洛,地道東北人树姨。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像桥状,于是被迫代替她去往敵國和親帽揪。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容