當(dāng)前位置:首頁(yè) > 公眾號(hào)精選 > 架構(gòu)師社區(qū)
[導(dǎo)讀]你是不是對(duì)于 MySQL 索引的知識(shí)點(diǎn)一直都像大雜燴,好像什么都知道,如果進(jìn)行深究的話可能一個(gè)也答不上來(lái)。

你是不是對(duì)于 MySQL 索引的知識(shí)點(diǎn)一直都像大雜燴,好像什么都知道,如果進(jìn)行深究的話可能一個(gè)也答不上來(lái)。

假如你去面試,面試官讓你聊一下對(duì)索引的理解,然而你對(duì)索引的理解僅限于,檢索數(shù)據(jù)就是快,是一種數(shù)據(jù)結(jié)構(gòu)這個(gè)層面,那你就只能回家等通知了。

為了避免這種尷尬的事情發(fā)生,咔咔用時(shí)兩天將索引的內(nèi)容在自己理解的范圍內(nèi)進(jìn)行了整理,如有整理不全面的地方可以在評(píng)論區(qū)進(jìn)行補(bǔ)充和提建議。

MySQL 索引到底是什么
相信大多數(shù)伙伴都買過(guò)技術(shù)類的書籍,看完沒(méi)看完不知道,但是目錄肯定看的次數(shù)最多。
看目錄有沒(méi)有自己目前的痛點(diǎn),如果有就會(huì)根據(jù)目錄對(duì)應(yīng)的頁(yè)碼用最快的速度翻閱到相應(yīng)內(nèi)容位置。
那么在 MySQL 中同樣也是這樣的一個(gè)道理,MySQL 的索引就是存儲(chǔ)引擎為了快速找到數(shù)據(jù)的一種數(shù)據(jù)結(jié)構(gòu)。
同樣在 MySQL 索引中又分了幾種類型,分別為:

  • B-tree 索引

  • 哈希索引

  • 空間索引

  • 全文索引

下文所有內(nèi)容均在 InnoDB 的基礎(chǔ)上討論。

為什么要使用索引

索引可以加快數(shù)據(jù)檢索速度,這也是使用的索引的最主要原因。

索引本身具有順序性,在進(jìn)行范圍查詢時(shí),獲取的數(shù)據(jù)已經(jīng)排好了序,從而避免服務(wù)器再次排序和建立臨時(shí)表的問(wèn)題。

索引的底層實(shí)現(xiàn)本身具有順序性,通過(guò)磁盤預(yù)讀使得在磁盤上對(duì)數(shù)據(jù)的訪問(wèn)大致呈順序的尋址,也就是將隨機(jī)的 I/O 變?yōu)轫樞?I/O

這幾點(diǎn)不理解就暫時(shí)先放著,繼續(xù)看下文即可,會(huì)給你一個(gè)滿意的解釋。

任何事物都存在雙面性,既然能提供性能的提升,自然在其他方面也會(huì)付出額外的代價(jià):

  • 索引是跟數(shù)據(jù)共存,因此會(huì)占用額外的存儲(chǔ)空間。

  • 索引創(chuàng)建和維護(hù)需要時(shí)間成本,這個(gè)成本隨著數(shù)據(jù)量的增大而增大。

  • 索引創(chuàng)建會(huì)降低數(shù)據(jù)的增、刪、改的性能,因?yàn)樵谛薷臄?shù)據(jù)的同時(shí)還需要修改索引數(shù)據(jù)。

InnoDB 為什么使用 B+Tree 而不使用 BTree
聊到這個(gè)問(wèn)題那就必須得分清楚 BTree、B+tree 的區(qū)別,首先來(lái)看一下 BTree。

Btree 解析
先來(lái)看一下 BTree 的數(shù)據(jù)結(jié)構(gòu)是怎么樣的,這里咔咔給提供一個(gè)網(wǎng)站地址,可以看到關(guān)于數(shù)據(jù)結(jié)構(gòu)的一些實(shí)現(xiàn)過(guò)程:

https://www.cs.usfca.edu/~galles/visualization/Algorithms.html 不會(huì)MySQL索引,面試官讓回家等通知!
 先來(lái)看 BTree 的數(shù)據(jù)結(jié)構(gòu),下圖是咔咔已經(jīng)將數(shù)據(jù)填充進(jìn)去的: 
不會(huì)MySQL索引,面試官讓回家等通知! 
這里有一個(gè)陌生區(qū)關(guān)于 Max. Degree,這個(gè)你可以理解為階,也可以理解為度。 
例如現(xiàn)在這個(gè)值設(shè)置的是 4,那么在一個(gè)節(jié)點(diǎn)中最多就可以存儲(chǔ) 3 條數(shù)據(jù),設(shè)置為 5那就可以最多放 4 條記錄。 

現(xiàn)在可以看到目前只插入了 3 條數(shù)據(jù):

不會(huì)MySQL索引,面試官讓回家等通知!

那么再加一條數(shù)據(jù),節(jié)點(diǎn)就會(huì)進(jìn)行分裂,這個(gè)也就驗(yàn)證了當(dāng)階設(shè)置為 n 時(shí),一個(gè)節(jié)點(diǎn)可存 n-1 條數(shù)據(jù)。

不會(huì)MySQL索引,面試官讓回家等通知!

那接著再來(lái)插入幾條數(shù)據(jù)看看:

不會(huì)MySQL索引,面試官讓回家等通知!

想要達(dá)到快速檢索數(shù)據(jù),那就需要滿足倆個(gè)特性,一個(gè)是有序,另一個(gè)就是平衡。
從下圖中可以看到 BTree 是有一定的順序性的,平衡性更滿足,可以看上文中生成的第一張圖。

不會(huì)MySQL索引,面試官讓回家等通知!

那么在 BTree 中找一個(gè)值是怎么找呢?例如現(xiàn)在要找一個(gè)值 9,看一下尋找過(guò)程。

首先看到的數(shù)據(jù)是 4,9 是大于 4 的,所以會(huì)往 4 的右節(jié)點(diǎn)尋找。繼續(xù)找到范圍在 6 到 8 的節(jié)點(diǎn),9 又大于 8,所以還需要往右節(jié)點(diǎn)尋找。
最有一步就找到了數(shù)據(jù) 9,這個(gè)過(guò)程就是 BTree 數(shù)據(jù)結(jié)構(gòu)查找數(shù)據(jù)的執(zhí)行過(guò)程。

不會(huì)MySQL索引,面試官讓回家等通知!

了解到了 BTree 的數(shù)據(jù)結(jié)構(gòu)后,我們?cè)趤?lái)看看在 MySQL 中關(guān)于 BTree 是如何存儲(chǔ)的。
在下圖中 P 代表的是指針,指向的是下一個(gè)磁盤塊。在第一個(gè)節(jié)點(diǎn)中的 16、24 就是代表我們的 key 值是什么。date 就是這個(gè) key 值對(duì)應(yīng)的這一行記錄是什么。

不會(huì)MySQL索引,面試官讓回家等通知!

那么此時(shí)想要尋找 key 為 33 的這條記錄應(yīng)該怎么找。33 在 16 和 34 中間,所以會(huì)去磁盤 3 進(jìn)行尋找。

在磁盤 3 中進(jìn)行判斷,指針指向磁盤 8。在磁盤 8 中即可獲取到數(shù)據(jù) 33,然后將 data 返回。

那么在這個(gè)過(guò)程中到底讀取了多少條數(shù)據(jù)呢?在計(jì)算之前需要先了解一些知識(shí)點(diǎn)。

從 MySQL 5.7 開(kāi)始,存儲(chǔ)引擎默認(rèn)為 innodb,并且 innodb 存儲(chǔ)引擎用于管理數(shù)據(jù)的最小磁盤單位就是頁(yè)。

這個(gè)頁(yè)的類型也分為好幾種,分別為數(shù)據(jù)頁(yè),Undo 頁(yè),系統(tǒng)頁(yè),事物數(shù)據(jù)頁(yè)。

一般說(shuō)到的頁(yè)都是數(shù)據(jù)頁(yè)。默認(rèn)的頁(yè)面大小為16kb,每個(gè)頁(yè)中至少存儲(chǔ)2條或以上的行記錄。

那么根據(jù) BTree 數(shù)據(jù)查找的過(guò)程中可以得知一共讀取了三個(gè)磁盤,那么每個(gè)磁盤的大小就是 16kb。

而目前的給的案例尋找了三層,那么三層存儲(chǔ)的數(shù)據(jù)就是:16kb*16kb*16kb=4096kb。

如果按照一條記錄所需內(nèi)存 1kb,那么這三層的 BTree 就可以存儲(chǔ) 4096 條記錄。

各位數(shù)據(jù)庫(kù)的數(shù)據(jù)少則幾百萬(wàn),多則幾千萬(wàn)數(shù)據(jù),那么 BTree 的層級(jí)就會(huì)越來(lái)越深,相對(duì)的查詢效率也會(huì)越來(lái)越慢。

這個(gè)時(shí)候是不是應(yīng)該思考一個(gè)問(wèn)題,那就是為什么在 Btree 中 48kb 的內(nèi)存怎么就只能存儲(chǔ) 4000 多條記錄?

問(wèn)題就出現(xiàn)在 data 上,要知道在計(jì)算數(shù)據(jù)大小時(shí)指針地址和 key 的內(nèi)存都是沒(méi)有計(jì)算在內(nèi)的,單單就計(jì)算了 data 的內(nèi)存。

因?yàn)樵?BTree 結(jié)構(gòu)中,節(jié)點(diǎn)中不僅存儲(chǔ)的有 key、指針地址還有對(duì)應(yīng)的數(shù)據(jù),所以就會(huì)造成單個(gè)磁盤存儲(chǔ)的數(shù)據(jù)相對(duì)很少的原因。

為了解決單個(gè)節(jié)點(diǎn)存儲(chǔ)數(shù)據(jù)量小的問(wèn)題,于是就演變出另一種結(jié)構(gòu),也就是下文提到了 B+Tree。

B+Tree 解析
依然如初看一下 B+Tree 的數(shù)據(jù)結(jié)構(gòu)。為了方便對(duì)比,將 BTree 和 B+Tree 的數(shù)據(jù)結(jié)構(gòu)放到了一起。 不會(huì)MySQL索引,面試官讓回家等通知!

那么可以看到在 B+Tree 中葉子節(jié)點(diǎn)是存放了全量的數(shù)據(jù),而非葉子節(jié)點(diǎn)只存儲(chǔ)了 key 值。

咦!這不是就很好的解決了 BTree 帶來(lái)的問(wèn)題嗎?可以讓每個(gè)節(jié)點(diǎn)存儲(chǔ)更多的數(shù)據(jù)。每個(gè)節(jié)點(diǎn)存儲(chǔ)的數(shù)據(jù)越多,那么相對(duì)的就是樹(shù)的深度就不會(huì)過(guò)深。
了解到了 B+Tree 的數(shù)據(jù)結(jié)構(gòu)后,我們?cè)趤?lái)看看在 MySQL 中關(guān)于 B+Tree 是如何存儲(chǔ)的。

不會(huì)MySQL索引,面試官讓回家等通知!

從上圖很明顯就可以看到兩點(diǎn)不同:

  • 第一點(diǎn):B+Tree 所有的數(shù)據(jù)都存儲(chǔ)在葉子節(jié)點(diǎn)上。

  • 第二點(diǎn):B+Tree 所有的葉子節(jié)點(diǎn)之間是一種鏈?zhǔn)江h(huán)結(jié)構(gòu)。

那么在這個(gè)過(guò)程中到底讀取了多少條數(shù)據(jù)呢?

如果說(shuō) B+Tree 讀取數(shù)據(jù)的深度跟 B-Tree 的深度一樣,都是三層,那么同樣的道理每個(gè)磁盤的大小為 16kb。

那在 B+Tree 中非葉子節(jié)點(diǎn)可以存儲(chǔ)多少數(shù)據(jù)呢!一般來(lái)說(shuō)我們每個(gè)表都會(huì)存在一個(gè)主鍵。

根據(jù)三層來(lái)計(jì)算,第一層跟第二層存儲(chǔ)的是 key 值,也就是主鍵值。

都知道 int 類型所占的內(nèi)存時(shí) 4Byte(字節(jié)),指針的存儲(chǔ)就給個(gè) 6Byte,一共就是 10Tybe,那么第一層節(jié)點(diǎn)就可以存儲(chǔ) 16*1000/10=1600。

同理第二層每個(gè)節(jié)點(diǎn)也是可以存儲(chǔ) 1600 個(gè) key。

第三層是葉子節(jié)點(diǎn),每個(gè)磁盤存儲(chǔ)大小同樣安裝 BTree 的計(jì)算一樣,每條數(shù)據(jù)占 1kb。

那么在 B+Tree 中三層可以存儲(chǔ)的數(shù)據(jù)就是 1600*1600*16=40960000。

從這點(diǎn)來(lái)看 B+Tree 存儲(chǔ)的數(shù)據(jù)跟 BTree 存儲(chǔ)的數(shù)據(jù)根本就不是一個(gè)級(jí)別。

所以可以得出結(jié)論:

  • B+Tree 能保證檢索的數(shù)據(jù)量相對(duì) BTree 是最多的,而且存儲(chǔ)的數(shù)據(jù)量也是最多的。

  • B+Tree 選擇索引時(shí)盡量選擇所占內(nèi)存空間小的類型,比如 int 類型。

  • key 所占內(nèi)存越小,在節(jié)點(diǎn)中存儲(chǔ)的范圍就越多。

Hash 索引

先來(lái)創(chuàng)建一個(gè) hash 索引:
alter table user add index hash_gender using hash(gender); 存儲(chǔ)引擎使用的是 innodb: 

不會(huì)MySQL索引,面試官讓回家等通知!

會(huì)發(fā)現(xiàn) name 的索引類型還是為 Btree,在 innodb 上創(chuàng)建哈希索引,被稱之為偽哈希索引,和真正的哈希索引不是一回事的,這點(diǎn)一定要明白。

在 Innodb 存儲(chǔ)引擎中有一個(gè)特殊的功能叫做,自適應(yīng)哈希索引,當(dāng)索引值被使用的非常頻繁時(shí),它會(huì)在內(nèi)存中基于 BTree 索引之上再創(chuàng)建一個(gè)哈希索引,那么就擁有了哈希索引的一些特點(diǎn),比如快速查找。
哈希索引就是基于哈希表實(shí)現(xiàn)的,假設(shè)對(duì) name 建立了哈希索引,則查找過(guò)程如下圖所示,哈希表是根據(jù)鍵值對(duì)進(jìn)行訪問(wèn)的數(shù)據(jù)結(jié)構(gòu),它讓檢索的數(shù)據(jù)經(jīng)過(guò)哈希函數(shù)映射到散列表的對(duì)應(yīng)位置,查找效率非常高。

不會(huì)MySQL索引,面試官讓回家等通知!

哈希索引存儲(chǔ)的是哈希值和行指針,沒(méi)有存儲(chǔ) key 值、字段值,但哈希索引多數(shù)是在內(nèi)存完成的,檢索數(shù)據(jù)是非??斓?,所以對(duì)性能影響不大:

  • 哈希索引不是按照索引值排序的,所以也就無(wú)法排序。

  • 哈希索引只支持等值操作,不支持范圍查找,在 MySQL 中只能只用 =、in 、<>。

  • 哈希索引在任何時(shí)候都不能避免表掃描。

  • 哈希索引在遇到大量哈希沖突時(shí),存儲(chǔ)引擎必須遍歷鏈表的所有行指針,逐行比較。

B+Tree 跟 BTree 區(qū)別

經(jīng)過(guò)了特別漫長(zhǎng)的計(jì)算、畫圖現(xiàn)在基本對(duì)倆者的區(qū)別有一定認(rèn)識(shí)了吧!

咔咔在這里進(jìn)行總結(jié)一下:

  • B+Tree 葉子節(jié)點(diǎn)上存儲(chǔ)的是全量數(shù)據(jù)(key+data),而非葉子節(jié)點(diǎn)只存儲(chǔ) key。

  • B+Tree 在同樣的深度下存儲(chǔ)的數(shù)據(jù)是遠(yuǎn)遠(yuǎn)大于 BTree 的。

  • B+Tree 每個(gè)葉子節(jié)點(diǎn)都有指向下一個(gè)葉子節(jié)點(diǎn)的鏈接。這樣的好處在于,我們可以從任意一個(gè)葉子節(jié)點(diǎn)開(kāi)始遍歷,獲取接下來(lái)所有的數(shù)據(jù)。

B+Tree 適合做索引的原因

B+Tree 樹(shù)非葉子節(jié)點(diǎn)只存儲(chǔ) key 值,因此相對(duì)于 BTree 節(jié)點(diǎn)可以存儲(chǔ)更多的數(shù)據(jù),每次讀入內(nèi)存的 key 值就更多,相對(duì)來(lái)說(shuō) I/O 就降低。

B+Tree 樹(shù)查詢效率穩(wěn)定,任何數(shù)據(jù)的查找都是必須從葉子節(jié)點(diǎn)到非葉子節(jié)點(diǎn),所以說(shuō)每個(gè)數(shù)據(jù)查找的效率幾乎都是相同的。

B+Tree 樹(shù)的葉子節(jié)點(diǎn)存儲(chǔ)的是全量數(shù)據(jù),并且是有序的,所以說(shuō)只需要遍歷葉子節(jié)點(diǎn)就可以對(duì)所有的 key 進(jìn)行掃描,在范圍查找時(shí)效率更高。

以上就是關(guān)于 InnoDB 存儲(chǔ)引擎為什么使用 B+Tree 作為索引的解析。

聚簇索引、非聚簇索引區(qū)別

聚簇索引、非聚簇索引也被稱之為主索引、二級(jí)索引。那么如何區(qū)分聚簇索引和非聚簇索引呢?
首先看一下 InnoDB 引擎下,創(chuàng)建表生成的文件,可以看到有兩個(gè) ibd 文件。

不會(huì)MySQL索引,面試官讓回家等通知!

看到這里不知道大家有沒(méi)有疑問(wèn):為什么看有的文章中也會(huì)有 frm 文件呢?但是在這里怎么沒(méi)有呢?

原因是在 MySQL 8.0 之后將源數(shù)據(jù)都存儲(chǔ)到了表空間中,所以也就不存在 frm 文件嘍!
都知道這個(gè) idb 文件會(huì)存儲(chǔ)數(shù)據(jù)信息和索引信息。那再來(lái)看一下 Myisam 存儲(chǔ)引擎創(chuàng)建表生產(chǎn)的文件。

不會(huì)MySQL索引,面試官讓回家等通知!

從圖中可以看到創(chuàng)建一個(gè)表會(huì)生成三個(gè)文件,擴(kuò)展名分別為 MYD、MYI、sdi:

  • MYD:是表數(shù)據(jù)文件(保存數(shù)據(jù)的文件)

  • MYI:是表索引文件(保存索引的文件)

那么就可以得出一個(gè)結(jié)論:只要數(shù)據(jù)跟索引存儲(chǔ)在一個(gè)文件里,那就是聚簇索引,否則就是非聚簇索引。

這個(gè)時(shí)候就會(huì)有人問(wèn)了,表中有主鍵的時(shí)候,idb 文件中存儲(chǔ)的是主鍵+數(shù)據(jù),那么當(dāng)沒(méi)有設(shè)置主鍵時(shí)怎么辦呢?

記住這一句話,在 InnoDB 中,數(shù)據(jù)插入時(shí)必須跟一個(gè)索引值進(jìn)行綁定,如果沒(méi)有主鍵那就選擇唯一索引,如果沒(méi)有唯一索引就會(huì)選擇一個(gè) 6Byte 的 rowid。

表中存在多個(gè)索引數(shù)據(jù)是如何存儲(chǔ)的

看了上文的解釋,有沒(méi)有產(chǎn)生過(guò)一絲疑問(wèn),在 InnoDB 存儲(chǔ)引擎下,如果存在多個(gè)索引,是不是會(huì)產(chǎn)生多個(gè) idb 文件。

在 InnoDB 中數(shù)據(jù)只會(huì)保存一份,如果有多個(gè)索引,會(huì)維護(hù)多個(gè) B+Tree,例如:表字段 id,name,age,sex。

id 設(shè)置為主鍵索引(聚簇索引),name 設(shè)置為普通索引,那么數(shù)據(jù)到底會(huì)存儲(chǔ)幾份呢?

不管一個(gè)表中設(shè)置多少個(gè)索引,數(shù)據(jù)只會(huì)存儲(chǔ)一份,但是這張表會(huì)維護(hù)多個(gè) B+Tree。

按照這個(gè)案例中 id 為主鍵索引,name 為普通索引,那么在這張表中就會(huì)維護(hù)倆顆 B+Tree。

id 主鍵索引跟數(shù)據(jù)存儲(chǔ)在一起,name 索引所在的 B+Tree 中葉子節(jié)點(diǎn)存儲(chǔ)的是主鍵 id 的值。
對(duì)應(yīng)的圖就是以下兩幅圖,可以好好的看一下: 不會(huì)MySQL索引,面試官讓回家等通知! 不會(huì)MySQL索引,面試官讓回家等通知!

最后給大家總結(jié)一個(gè)點(diǎn):在 InnoDB 中,一定有聚簇索引,其它索引都是非聚簇索引。

這里簡(jiǎn)單提一下:Myisam 中只有非聚簇索引。

索引的幾個(gè)技術(shù)名詞

在面試中往往會(huì)問(wèn)這幾個(gè)關(guān)鍵詞,分別為回表、覆蓋索引、最左側(cè)原則、索引下推,一定要知道哈!

回表

網(wǎng)上對(duì)回表的解釋各種各樣,咔咔給你說(shuō)種簡(jiǎn)單易懂的,但前提是你需要把聚簇索引、非聚簇索引區(qū)分清楚。

還是用上邊的案例,id 為主鍵索引,name 為普通索引。此時(shí)查詢語(yǔ)句為:

select id,name,age from table where name = 'kaka' 

那么這條語(yǔ)句會(huì)先在 name 的這顆 B+Tree 中尋找到主鍵 id,然后在根據(jù)主鍵 id 的索引獲取到數(shù)據(jù)并且返回。
其實(shí)這個(gè)過(guò)程就是從非聚簇索引跳轉(zhuǎn)到聚簇索引中查找數(shù)據(jù),被稱為回表,也就是說(shuō)當(dāng)你查詢的字段為非聚簇索引,但是非聚簇索引中沒(méi)有將需要查詢的字段全部包含就是回表。

在這個(gè)案例中,非聚簇索引 name 的葉子節(jié)點(diǎn)只有 id,并沒(méi)有 age,所以會(huì)跳轉(zhuǎn)到聚簇索引中,根據(jù) id 在查詢整條記錄返回需要的字段數(shù)據(jù)。

覆蓋索引

覆蓋索引,根據(jù)名字都能理解的差不多,就是查詢的所有字段都創(chuàng)建了索引!

此時(shí)查詢語(yǔ)句為:
select id,name from table where name = 'kaka' 

那么這條語(yǔ)句就是使用了覆蓋索引,因?yàn)?id 和 name 都為索引字段,查詢的字段也是這倆個(gè)字段,所以被稱為索引覆蓋。
也就是說(shuō)當(dāng)非覆蓋索引的葉子節(jié)點(diǎn)中包含了需要查詢的字段時(shí)就被稱為覆蓋索引。

最左匹配

最左匹配原則是在組合索引中存在的。還是用之前表信息:表字段 id,name,age,sex。此時(shí)給 name,age 設(shè)置成組合索引。
以下語(yǔ)句中那個(gè)不符合最左側(cè)原則:

select * from table where name = ? and age = ? select * from table where name = ? select * from table where age = ? select * from table where age= ? and name= ?

可以自行做一下測(cè)驗(yàn)哈!是只有第三條語(yǔ)句不會(huì)用到索引,其他的三條語(yǔ)句都會(huì)符合最左側(cè)原則。
關(guān)于這個(gè)最左側(cè)原則遠(yuǎn)遠(yuǎn)不止這么簡(jiǎn)單的,一試就是一個(gè)坑,關(guān)于這部分內(nèi)容咔咔后期會(huì)在優(yōu)化文章中提到。

索引下推

還是使用這條 sql 語(yǔ)句:

select * from table where name = ? and age = ?

索引下推是在 MySQL 5.6 及以后的版本出現(xiàn)的。之前的查詢過(guò)程是,先根據(jù) name 在存儲(chǔ)引擎中獲取數(shù)據(jù),然后在根據(jù) age 在 server 層進(jìn)行過(guò)濾。

在有了索引下推之后,查詢過(guò)程是根據(jù) name、age 在存儲(chǔ)引擎獲取數(shù)據(jù),返回對(duì)應(yīng)的數(shù)據(jù),不再到 server 層進(jìn)行過(guò)濾。
當(dāng)你使用 Explain 分析 SQL 語(yǔ)句時(shí),如果出現(xiàn)了 Using index condition 那就是使用了索引下推,索引下推是在組合索引的情況出現(xiàn)幾率最大的。

索引存儲(chǔ)在什么地方
索引的數(shù)據(jù)文件是存儲(chǔ)在磁盤中的,也是需要進(jìn)行持久化操作。但是當(dāng)使用索引時(shí)會(huì)把數(shù)據(jù)從磁盤讀取到內(nèi)存中,讀取方式為分塊讀取。

這時(shí)就要涉及到操作系統(tǒng)的概念,操作系統(tǒng)在磁盤中獲取數(shù)據(jù),假設(shè)現(xiàn)在要取的數(shù)據(jù)大小是 1kb,但操作系統(tǒng)并不會(huì)只取出你需要的這 1kb,而是會(huì)取出 4kb 的數(shù)據(jù)。
為什么會(huì)是 4kb,因?yàn)樵诓僮飨到y(tǒng)中一頁(yè)的數(shù)據(jù)就是 4kb。那又為什么只需要 1kb 而取出整頁(yè)的數(shù)據(jù)呢?

那就又會(huì)涉及到另一個(gè)概念那就是局部性原理:數(shù)據(jù)和程序都有聚集成群的傾向,在訪問(wèn)了一條數(shù)據(jù)之后,在之后有極大的可能再次訪問(wèn)這條數(shù)據(jù)和這條數(shù)據(jù)的相鄰數(shù)據(jù)。
所以說(shuō) MySQL 的 InnoDB 存儲(chǔ)引擎,在讀取數(shù)據(jù)時(shí)也會(huì)采取這種局部性原理,每次讀取的數(shù)據(jù)是 16kb。

在 InnoDB 存儲(chǔ)引擎下每頁(yè)的大小默認(rèn)為 16kb,這個(gè)參數(shù)也可以進(jìn)行調(diào)整,參數(shù)為 innodb_page_size。
最后一點(diǎn): 既然標(biāo)題問(wèn)的是索引數(shù)據(jù)存儲(chǔ)在什么地方,在第一句就直接回答了索引是存儲(chǔ)在磁盤中,并且以頁(yè)為單位進(jìn)行從磁盤往內(nèi)存讀取。
那為什么不直接存儲(chǔ)在內(nèi)存中呢?你有沒(méi)有這個(gè)疑問(wèn)呢?

如果索引數(shù)據(jù)只存儲(chǔ)在內(nèi)存中,那么當(dāng)電腦關(guān)機(jī),服務(wù)器宕機(jī)之后,就需要重新生成索引,這種的效率是十分低的。

總結(jié)

以上就是咔咔對(duì)索引的理解,在盡最大的可能將知識(shí)點(diǎn)說(shuō)全面。如果還有遺漏,或者文章中有錯(cuò)誤的地方還請(qǐng)各位能給出提議。


免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關(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)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉