MySQL 索引工作原理

2022-09-07 11:06:10 字數 2590 閱讀 1607

為什麼需要索引(why is it needed)?

當資料儲存在磁碟類儲存介質上時,它是作為資料塊存放。這些資料塊是被當作乙個整體來訪問的,這樣可以保證操作的原子性。硬碟資料塊儲存結構類似於鍊錶,都包含資料部分,以及乙個指向下乙個節點(或資料塊)的指標,不需要連續儲存。

記錄集只能在某個關鍵字段上進行排序,所以如果需要在乙個無序欄位上進行搜尋,就要執行乙個線性搜尋(linear search)的過程,平均需要訪問n/2的資料塊,n是表所佔據的資料塊數目。如果這個欄位是乙個非主鍵字段(也就是說,不包含唯一的訪問入口),那麼需要在n個資料塊上搜尋整個**空間。

但是對於乙個有序字段,可以運用二分查詢(binary search),這樣只要訪問log2 (n)的資料塊。這就是為什麼效能能得到本質上的提高。

什麼是索引(what is indexing)?

索引是對記錄集的多個字段進行排序的方法。在一張表中為乙個字段建立乙個索引,將建立另外乙個資料結構,包含字段數值以及指向相關記錄的指標,然後對這個索引結構進行排序,允許在該資料上進行二分法排序。

***是索引需要額外的磁碟空間,對於myisam引擎而言,這些索引是被統一儲存在一張表中的,這個檔案將很快到達底層檔案系統所能夠支援的大小限制,如果很多欄位都建立了索引的話。

索引如何工作(how does it work?)

首先,我們建立乙個示範資料庫表:

欄位名 資料型別 大小

id (primary key) unsigned int 4 bytes

firstname char(50) 50 bytes

lastname char(50) 50 bytes

emailaddress char(100) 100 bytes

注意:使用char是為了指定準確的磁碟占用大小。這個示範資料庫包含500萬行,而且沒有索引。我們將分析一些查詢語句的效能,乙個是使用主鍵id(有序)查詢,乙個是使用firstname(非關鍵無序字段)。

例1

我們的示範資料庫有r=5,000,000條記錄,每條記錄長度r=204位元組而且使用myisam引擎儲存(預設資料塊大小為b=1024位元組),這張表的塊因子(blocking factor)會是bfr = (b/r) = 1024/204 = 5 條記錄每磁碟資料塊。儲存這張表所需要的磁碟塊為n = (r/bfr) = 5000000/5 = 1,000,000 blocks。

在id欄位上的線性搜尋平均需要n/2 = 500,000塊訪問來找到一條記錄假設id欄位是查詢關鍵值,不過既然id欄位是有序的,可以執行乙個二分查詢,這樣平均只需要訪問log2 (1000000) = 19.93 = 20 個資料塊。我們馬上就看到了極大的提高。

現在firstname欄位既不是有序的,無法執行二分搜尋,數值也不具有唯一性,所以對這張表的查詢必須到最後乙個記錄即全表掃瞄n = 1,000,000個資料塊訪問。這就是索引用來改進的地方。

假如索引記錄只包含乙個索引列以及乙個指向原記錄資料的指標,那麼它顯而易見會比原記錄(多列)要小。所以索引本身所需要的磁碟塊要更少,掃瞄數目也少。firstname索引表結構如下:

field name data type size on disk

firstname char(50) 50 bytes

(record pointer) special 4 bytes

注意: mysql裡的指標按表大小的不同分別可能是 2, 3, 4 或 5 個位元組。

例2

假設我們的資料庫有r = 5,000,000 條記錄,建立了乙個長r = 54位元組的索引,並且使用預設磁碟塊大小為1,024位元組。那麼該索引的塊因子為bfr = (b/r) = 1024/54 = 18 條記錄每磁碟塊。容納這個索引表總共需要的磁碟塊為n = (r/bfr) = 5000000/18 = 277,778 塊。

現在使用firstname欄位來進行搜尋就可以利用索引來提高效能。這允許使用乙個二分查詢,平均log2 (277778) = 18.08 -> 19次資料塊訪問。找到實際記錄的位址,這需要進一步的塊讀取,這樣總數達到19 + 1 = 20次資料塊訪問,這和非索引表的資料塊訪問次數有天壤之別。

什麼時候使用索引(when should it be used?)

鑑於建立索引需要額外的磁碟空間(上面的例子需要額外的277778個磁碟塊),以及太多的索引會導致檔案系統大小限制所產生的問題,所以對哪些字段建立索引,什麼情況下使用索引,需要審慎考慮。

由於索引只是用來加速資料查詢,那麼顯然對只是用來輸出的字段建立索引會浪費磁碟空間以及發生插入、刪除操作時的處理時間,所以這種情況下應該盡量避免。

鑑於二分搜尋的特性,資料的基數或獨立性是很重要的。

在基數為2的字段上建立索引,將把資料分割一半,而基數為1000則將返回大約1000條記錄。低基數的二分查詢效率將降低為乙個線性排序,而且查詢優化器可能會在基數小於記錄數某個比例時(如30%)的情況下將避免使用索引而直接查詢原表,所以這種情況下的索引浪費了空間。

**:

MySQL索引原理之索引原理

索引定義 是儲存引擎用於快速查詢記錄的一種資料結構。需要額外開闢空間和資料維護工作。索引是物理資料頁儲存,在資料檔案中 innodb,ibd檔案 利用資料頁 page 儲存。索引可以加快檢索速度,但是同時也會降低增刪改操作速度,索引維護需要代價。索引涉及的理論知識 二分查詢法 hash和b tree...

mysql索引 mysql索引實現原理

什麼是索引 索引是一種高效獲取資料的儲存結構,例 hash 二叉 紅黑。mysql為什麼不用上面三種資料結構而採用b tree 若僅僅是 select from table where id 45 上面三種演算法可以輕易實現,但若是select from table where id 6 就不好使了...

mysql 索引原理

b樹 b樹高度 資料庫為什麼使用這種結構?一般來說,索引本身也很大,不可能全部儲存在記憶體中,因此索引往往以索引檔案的形式儲存的磁碟上。這樣的話,索引查詢過程中就要產生磁碟i o消耗,相對於記憶體訪問,i o訪問的消耗要高幾個數量級,所以評價乙個資料結構作為索引的優劣最重要的指標就是在查詢過程中磁碟...