MySQL InnoDB索引原理詳解

2021-09-28 19:43:04 字數 4253 閱讀 6166

1 簡介

索引(index)是幫助mysql高效獲取資料的資料結構。我們知道,資料庫查詢是資料庫的最主要功能之一。但每種查詢演算法都只能應用於特定的資料結構之上,例如二分查詢要求被檢索資料有序,而二叉樹查詢只能應用於二叉查詢樹上,但是資料本身的組織結構不可能完全滿足各種資料結構(例如,理論上不可能同時將兩列都按順序進行組織),所以,在資料之外,資料庫系統還維護著滿足特定查詢演算法的資料結構,這些資料結構以某種方式引用(指向)資料,這樣就可以在這些資料結構上實現高階查詢演算法。這種資料結構,就是索引。

索引一般以檔案形式儲存在磁碟上,索引檢索需要磁碟i/o操作。所以評價乙個資料結構作為索引的優劣最重要的指標就是在查詢過程中磁碟i/o操作次數的漸進複雜度。在mysql中,索引屬於儲存引擎級別的概念,不同儲存引擎對索引的實現方式是不同的(例如樹結構的選型和查詢演算法的實現),本文主要討論innodb的索引實現方式。

當資料儲存在磁碟類儲存介質上時,它是作為資料塊存放。這些資料塊是被當作乙個整體來訪問的,這樣可以保證操作的原子性。硬碟資料塊儲存結構類似於鍊錶,都包含資料部分,以及乙個指向下乙個節點(或資料塊)的指標,不需要連續儲存。所以-- 可以說資料庫必須有索引,沒有索引則檢索過程變成了順序查詢,o(n)的時間複雜度幾乎是不能忍受的。另一篇文章也會介紹mysql中如何建立索引。mysql索引建立(innodb)需要注意,某些操作會使得資料庫放棄索引而進行全表掃瞄。導致引擎放棄使用索引而進行全表掃瞄的條件。

2在 innodb 中,索引使用的資料結構是 b+ tree

這裡的 b 是 balance 的意思。b 類樹的乙個很鮮明的特點就是樹的層數比較少,而每層的節點都非常多,樹的每個葉子節點到根節點的距離都是相同的(這也是為什麼叫 balance tree 的原因)。另外,樹的每乙個節點都是乙個資料頁,這樣每個節點只需要一次 io 就可以全部讀取。這樣的結構保證了查詢資料時能盡量少地進行磁碟 io,同時保證 io 的穩定性。b+ tree 和 b tree 不同,b+ tree 中,只能將資料儲存在葉子結點中,內部節點將只包含指標,而 b tree 可以將資料儲存在內部的葉節點中。因此 b+ tree 的關鍵優勢是中間節點不包含資料,因此 b+ tree 的大小遠小於 b tree,並且可以將更多資料儲存到儲存器中。另外,b+ tree 的每乙個葉子節點包含了到相鄰的節點的鏈結,這樣可以快速地進行範圍遍歷。

為什麼用b+ree 做索引

1)  b+數是由b-數演變而來,所以b+數擁有b-數的所有特性

2)  b+樹的非葉子節點只儲存關鍵字和子節點的位址,而葉子節點保留了當前路節點的所有節點的關鍵字、資料區和位址,所以要得到節點的資料就要到葉子節點上去獲取,所以我們每次對資料的檢索的時間都差不多,不像其他樹,非葉子節點也有保留資料區,這樣子當資料量龐大,當檢索第乙個跟最後乙個的索引時間就相差比較大

3)  b+樹是一顆多路平衡查詢樹,由於它是多路的,所以它的高度比其他二叉樹都矮,樹的高度決定了檢索資料的時間複雜度

計算機預設檢索的一頁是4k,而mysql對這個4k做了調整增加到16k,這個一頁是16k,假如這裡儲存的是乙個id的索引樹,那id設定為int型別,乙個int型別為4個位元組,那這一頁可以儲存的id的個數就可以這樣算((16* 1024)/4),所以索引的型別和位元組數都決定了資料庫檢索資料的效率,所以該id樹的乙個節點可以設定的路數就為((16*1024)/4)路,所以這一頁就可以儲存這麼多資料,一次載入到記憶體中就可以載入那麼多,充分利用了計算機的io讀取效能和空間區域性性原理,極大降低了計算機io的次數

4)  b+樹的葉子節點上儲存乙個指標,這個指標指向的是下乙個葉子節點的指標,譬如第一路的葉子節點上資料有567這三個樹,而第二路有8910,則第一路的7有個指標會指向第二路的8,這樣做的好處是使資料自帶有順序性的特性,這個順序性在我們做乙個範圍查詢時,效能就得到充分的發揮,這個指標也是b-樹跟b+樹的區別之一

mysql 索引為什麼要選用 b+ tree

3 主索引和輔助索引

在 innodb 儲存引擎中,每乙個索引都對應一棵 b+ tree,innodb 的索引主要分為主索引和輔助索引:

主索引:包含記錄的檔案按照某個 key 制定的順序排序,這個 key 就是主索引,也就是主鍵,也被稱為聚簇索引。因為無法同時把資料行存放在兩個不同的地方,所以乙個表只能有乙個聚集索引。在 innodb 中,主索引的葉子節點存的是整行資料,這也意味著 innodb 中的表一定要有乙個主索引;

輔助索引:某個 key 指定的順序與檔案記錄的物理順序不同,這個 key 就是輔助索引。innodb 中的輔助索引在葉子節點中並不儲存實際的資料,只會包含主索引的值 。這就意味著如果使用輔助索引進行資料的查詢,只能查到主索引,然後根據這個主索引再次掃瞄以下主索引的樹,進行一次回表操作;

上面講到,innodb 的表中要求必須有乙個主鍵,那麼可能有人會將身份證號這種唯一性的標識作為主索引,這樣就大錯特錯了。剛剛說到主鍵也被稱為聚簇索引,它是要按照順序進行排序的,要求有聚簇性。如果將身份證號作為主鍵,不能保證每次插入的資料都是按照身份證號的順序進行排列的,這就使得每次主鍵的插入都變得完全隨機,可能導致每次插入一條資料都會引起頁**的問題。

所以在表結構定義的時候,應該使用乙個具有聚集性的 key 作為主鍵,如果真的沒有的話,可以使用乙個 auto increment **鍵作為主索引,這樣可以保證資料行是順序寫入的。如果你真的完全沒有定義主鍵,innodb 會選擇乙個唯一的非空索引代替,但是如果沒有這樣的索引,innodb 會隱式定義乙個主鍵來作為聚集索引。

正因為 innodb 索引的這種結構,產生了一些限制:

1 如果不是按照索引的最左列開始查詢,則無法使用索引;

2 不能跳過聯合索引中的某些列;

3 如果查詢中有某個列的範圍查詢,則其右邊所有列都無法使用索引優化查詢;

4 雜湊索引

innodb儲存引擎使用雜湊演算法來查詢字典,衝突機制採用鍊錶,雜湊函式採用除法雜湊。對於緩衝池的雜湊表,在快取池中的每頁都有乙個chain指標,指向相同雜湊值的頁。對於除法雜湊,m的值為略大於2倍緩衝池頁數量的質數。如當前innodb_buffer_pool_size大小為10m,則共有640個16kb的頁,需要分配1280個插槽,而略大於的質數為1399,因此會分配1399個槽的雜湊表,用來雜湊查詢緩衝池中的頁。 而對於將每個頁轉換為自然數,每個表空間都有乙個space_id,使用者要查詢的是空間中某個連續的16kb的頁,即偏移量(offset),innodb將space_id左移20位,再加上space_id和offset,即k=space_id<<20+space_id+offset,然後使用除法雜湊到各個槽中。

自適應雜湊索

自適應雜湊索引採用之前討論的雜湊表的方式實現。不同的是,這僅是資料庫自身建立並使用的,dba本身並不能對其進行干預。自適應雜湊索引經雜湊函式對映到乙個雜湊表中,因此對於字典型別的查詢非常快速,如 select* from table where index col=***。但是對於範圍查詢就無能為力了。通過命令 show engine innodb status可以看到當前自適應雜湊索引的使用狀況。

5 全文索引

通過前面章節的介紹,已經知道b+樹索引的特點,可以通過索引欄位的字首( prefix)進行查詢。例如,對於下面的查詢b+樹索引是支援的:select from blog where content like '***s上述sol語句可以查詢部落格內容以x開頭的文章,並且只要 content新增了b+樹索引,就能利用索引進行快速查詢。然而實際這種查詢不符合使用者的要求,因為在更多的情況下,使用者需要查詢的是部落格內容包含單詞***的文章,即:select from blog where content like ' 8***8根據b+樹索引的特性,上述sql語句即便新增了b+樹索引也是需要進行索引的掃瞄來得到結果。類似這樣的需求在網際網路應用中還有很多。例如,搜尋引擎需要根據使用者輸入的關鍵字進行全文查詢,電子商務**需要根據使用者的查詢條件,在可能需要在商品的詳細介紹中進行查詢,這些都不是b+樹索引所能很好地完成的工作。全文檢索(fu- text search)是將儲存於資料庫中的整本書或整篇文章中的任意內容資訊查詢出來的技術。它可以根據需要獲得全文中有關章、節、段、句、詞等資訊,也可以進行各種統計和分析。在之前的 mysql資料庫中, innodb儲存引擎並不支援全文檢索技術,從innodb 1.2.x開始支援。

mysql · 引擎特性 · innodb 全文索引簡介

mysql中innodb全文檢索

MySQL Innodb 索引的原理

回想四年前,我在學習mysql的索引這塊的時候,老師在講索引的時候,是像下面這麼說的 索引就像一本書的目錄。而當使用者通過索引查詢資料時,就好比使用者通過目錄查詢某章節的某個知識點。這樣就幫助使用者有效地提高了查詢速度。所以,使用索引可以有效地提高資料庫系統的整體效能。嗯,這麼說其實也對。但是呢,大...

MySQL Innodb 索引的原理

回想四年前,我在學習mysql的索引這塊的時候,老師在講索引的時候,是像下面這麼說的 索引就像一本書的目錄。而當使用者通過索引查詢資料時,就好比使用者通過目錄查詢某章節的某個知識點。這樣就幫助使用者有效地提高了查詢速度。所以,使用索引可以有效地提高資料庫系統的整體效能。嗯,這麼說其實也對。但是呢,大...

MySQL InnoDB索引相關

一般資料庫的資料 資料本身和結構維護資料 最終都是要落地到磁碟上,進行讀取的時候不可能一次性將所有資料全部載入到記憶體,所以記憶體中需要不停的置換磁碟上的內容,索引也是一樣,乙個資料庫的索引佔據的空間也是不小的資料,都是分頁載入的,所以需要合適的資料結構來儲存才能保持較好的效能,b樹就是用來儲存索引...