1. 程式人生 > >資料庫索引原理解析

資料庫索引原理解析

資料庫索引原理解析

什麼是全表掃描?

瞭解索引之前,我們先搞懂什麼是全表掃描。假設在mysql資料庫裡有一個user表如下:
在這裡插入圖片描述
現在我們要從這個表中查找出所有名字是‘李四’的使用者資訊。我們使用下面的查詢語句:

SELECT * FROM user WHERE name = '李四';

一旦我們執行這個查詢,在查詢名字為‘李四’的使用者的過程中,究竟會發生什麼?資料庫不得不把user表中的每一行查一遍,並確定使用者的名字(name)是否為 ‘李四’。由於我們想要得到每一個名字為‘李四’的使用者資訊,在查詢到第一個符合條件的行後,不能停止查詢,因為可能還有其他符合條件的行。所以,必須一行一行的查詢直到最後一行,這就意味資料庫不得不檢查上千行資料才能找到名字為‘李四’的使用者。這就是所謂的全表掃描。

什麼是索引?

一個索引是儲存著表中一個特定列的值的資料結構(最常見的是B-Tree)。索引在表的列上建立。所以,要記住的關鍵點是索引包含一個表中列的所有值,並且這些值儲存在一個數據結構中。一定記住:索引是一種資料結構 。

索引是怎麼提升效能的?

因為索引基本上是用來儲存列值的資料結構,這使查詢這些列值更加快速。如果索引使用最常用的資料結構-B-Tree-那麼其中的資料是有序的。有序的列值可以極大的提升效能。下面解釋原因。

在資料之外,資料庫系統還維護著滿足特定查詢演算法的資料結構。這些資料結構以某種方式引用(指向)資料,這樣就可以在這些資料結構上實現高階查詢演算法。這種資料結構就是索引

假設我們在 name這一列上建立一個B-Tree索引。這意味著當我們用之前的SQL查詢姓名是‘李四’的使用者時,不需要再掃描全表。而是用索引去查詢名字為‘李四’的使用者,因為索引已經按照按字母順序排序。索引已經排序意味著查詢一個名字會快很多,因為名字首字母為‘l’的使用者都是排列在一起的。抽象出來的圖如下:
在這裡插入圖片描述
另外重要的一點是,索引同時儲存了表中相應行的指標以獲取其他列的資料。

資料庫索引裡究竟存的是什麼?

現在已經知道資料庫索引是建立在表的某列上的,並且儲存了這一列的所有值。但是,需要理解的重點是索引並不儲存這個表中其他列(欄位)的值。舉例來說,如果我們在name列建立索引,那麼列id,sex,address上的值並不會儲存在這個索引當中。如果我們確實把其他所有欄位也儲存在個這個索引中,那就成了拷貝一整張表做為索引,這樣會佔用太大的空間而且會十分低效。

索引儲存了指向表中某一行的指標

如果我們在索引裡找到某一條記錄作為索引的列的值,如何才能找到這一條記錄的其它值呢?這是很簡單 ,資料庫索引同時儲存了指向表中的相應行的指標。指標是指一塊記憶體區域, 該記憶體區域記錄的是對硬碟上記錄的相應行的資料的引用。因此,索引中除了儲存列的值,還儲存著一個指向在行資料的索引。也就是說,索引中的name這列的某個值(或者節點)可以描述為 (“李四”, 0x82829), 0x82829 就是包含“李四”那行資料在硬碟上的地址。如果沒有這個引用,你就只能訪問到一個單獨的值(“李四”),而這樣沒有意義,因為你不能獲取這一行記錄的user的其他值,例如(id),年齡(sex)和地址(address)。

資料庫怎麼知道什麼時候使用索引?

當這個SQL (SELECT * FROM userWHERE name= ‘李四’ ;)執行時,資料庫會檢查在查詢的列上是否有索引。假設name列上確實建立了索引,資料庫會接著檢查使用這個索引做查詢是否合理,因為有些場景下,使用索引比起全表掃描會更加低效。