1. 程式人生 > 實用技巧 >MySQL-Innodb 引擎和 Myisam 引擎的實現

MySQL-Innodb 引擎和 Myisam 引擎的實現

Mysql 底層資料引擎以外掛形式設計,最常見的是 Innodb 引擎Myisam 引擎,使用者可以根據個人需求選擇不同的引擎作為 Mysql 資料表的底層引擎。我們剛分析了,B+樹作為 Mysql 的索引的資料結構非常合適,但是資料和索引到底怎麼組織起來也是需要一番設計,設計理念的不同也導致了 Innodb 和 Myisam 的出現,各自呈現獨特的效能。

MyISAM 雖然資料查詢效能極佳,但是不支援事務處理。Innodb 最大的特色就是支援了 ACID 相容的事務功能,而且他支援行級鎖。Mysql 建立表的時候就可以指定引擎,比如下面的例子,就是分別指定了 Myisam 和 Innodb 作為 user 表和 user2 表的資料引擎。

在這裡插入圖片描述
執行這兩個指令後,系統出現了以下的檔案,說明這兩個引擎資料和索引的組織方式是不一樣的。
在這裡插入圖片描述
Innodb 建立表後生成的檔案有:

  • frm:建立表的語句
  • idb:表裡面的資料+索引檔案

Myisam 建立表後生成的檔案有:

  • frm:建立表的語句
  • MYD:表裡面的資料檔案(myisam data)
  • MYI:表裡面的索引檔案(myisam index)

從生成的檔案看來,這兩個引擎底層資料和索引的組織方式並不一樣,MyISAM 引擎把資料和索引分開了,一人一個檔案,這叫做非聚集索引方式;Innodb 引擎把資料和索引放在同一個檔案裡了,這叫做聚集索引方式。下面將從底層實現角度分析這兩個引擎是怎麼依靠 B+樹這個資料結構來組織引擎實現的。

MyISAM 引擎的底層實現(非聚集索引方式)

MyISAM 用的是非聚集索引方式,即資料和索引落在不同的兩個檔案上。MyISAM 在建表時以主鍵作為 KEY 來建立主索引 B+樹,樹的葉子節點存的是對應資料的實體地址。我們拿到這個實體地址後,就可以到 MyISAM 資料檔案中直接定位到具體的資料記錄了。
在這裡插入圖片描述
當我們為某個欄位新增索引時,我們同樣會生成對應欄位的索引樹,該欄位的索引樹的葉子節點同樣是記錄了對應資料的實體地址,然後也是拿著這個實體地址去資料檔案裡定位到具體的資料記錄。

Innodb 引擎的底層實現(聚集索引方式)

InnoDB 是聚集索引方式,因此資料和索引都儲存在同一個檔案裡。首先 InnoDB 會根據主鍵 ID 作為 KEY 建立索引 B+樹,如左下圖所示,而 B+樹的葉子節點儲存的是主鍵 ID 對應的資料,比如在執行 select * from user_info where id=15 這個語句時,InnoDB 就會查詢這顆主鍵 ID 索引 B+樹,找到對應的 user_name=‘Bob’。

這是建表的時候 InnoDB 就會自動建立好主鍵 ID 索引樹,這也是為什麼 Mysql 在建表時要求必須指定主鍵的原因。當我們為表裡某個欄位加索引時 InnoDB 會怎麼建立索引樹呢?比如我們要給 user_name 這個欄位加索引,那麼 InnoDB 就會建立 user_name 索引 B+樹,節點裡存的是 user_name 這個 KEY,葉子節點儲存的資料的是主鍵 KEY。注意,葉子儲存的是主鍵 KEY!拿到主鍵 KEY 後,InnoDB 才會去主鍵索引樹里根據剛在 user_name 索引樹找到的主鍵 KEY 查詢到對應的資料。
在這裡插入圖片描述
問題來了,為什麼 InnoDB 只在主鍵索引樹的葉子節點儲存了具體資料,但是其他索引樹卻不存具體資料呢,而要多此一舉先找到主鍵,再在主鍵索引樹找到對應的資料呢?

其實很簡單,因為 InnoDB 需要節省儲存空間。一個表裡可能有很多個索引,InnoDB 都會給每個加了索引的欄位生成索引樹,如果每個欄位的索引樹都儲存了具體資料,那麼這個表的索引資料檔案就變得非常巨大(資料極度冗餘了)。從節約磁碟空間的角度來說,真的沒有必要每個欄位索引樹都存具體資料,通過這種看似“多此一舉”的步驟,在犧牲較少查詢的效能下節省了巨大的磁碟空間,這是非常有值得的。

在進行 InnoDB 和 MyISAM 特點對比時談到,MyISAM 查詢效能更好,從上面索引檔案資料檔案的設計來看也可以看出原因:MyISAM 直接找到實體地址後就可以直接定位到資料記錄,但是 InnoDB 查詢到葉子節點後,還需要再查詢一次主鍵索引樹,才可以定位到具體資料。等於 MyISAM 一步就查到了資料,但是 InnoDB 要兩步,那當然 MyISAM 查詢效能更高。

最後再總結一下什麼時候需要表裡的欄位加索引:

  • 較頻繁的作為查詢條件的欄位應該建立索引
  • 唯一性太差的欄位不適合單獨建立索引,即使該欄位頻繁作為查詢條件
  • 更新非常頻繁的欄位不適合建立索引