MySQL之存儲引擎InnoDB和MyISAM的區別及底層詳解

題外話:中華文化博大進深,從學Java到數據庫,無一不體現出同一組件魚和熊掌不可兼得的要義。天然,編程中安全和效率也很難同時作到完美,這一次InnoDB和MyISAM又讓我大開眼界。mysql

好了,Talk is cheap,show you the code:算法

測試環境:Mysql 5.7.20-log,IDEA 2018sql

首先建立兩張表: testinnodb,testmyisam,sql以下:數據庫

Mysql之存儲引擎InnoDB和MyISAM的區別及底層詳解

1.同時大批量插入數據(百萬級,million),小編採用了存儲過程,代碼及測試結果以下:編程

下面代碼在IDEA上運行便可:
緩存

同時插入100W條數據,MyISAM耗時38s左右,而InnoDB卻耗時76分鐘4s左右,很明顯能夠看出MyISAM在處理速度上完勝InnoDB,可是若是實際項目中使用,因爲涉及到數據安全(或者事物安全)問題,大多數公司仍是選擇了InnoDB, 較少公司使用MyISAM(得力於其在業務層的嚴格控制)。但MyISAM依然能夠被咱們使用在日誌數據分析,實驗等環境中。安全

2.再看其在刪改查方面的對比性能優化

改查耗時服務器

刪除耗時併發

其實對比下來,差距並無插入數據那樣誇張,對於大多數要求事物安全的公司來講仍是能夠接受的。

PS: 你可使用mysql插件profile來顯示最近執行命令的持續時長,用法以下:

mysql默認是關閉profiles的,你須要開啓它,

查看是否開啓命令: show variables like '%pro%';

小編已經把他開啓了,因此顯示爲ON,默認爲OFF。

開啓命令:set profiling=1;

關閉命令:set profiling=0;

查詢最近使用命令時長:show profiles;

根據Query ID查詢單個命令詳情: show profile for query 1;

根據Query ID查詢單個命令memory,source,cpu等詳情: show profile cpu for query 1;或者 show profile all for query 1;

測試Over,接下來總結一下:

1.InnoDB支持事物,外鍵等高級的數據庫功能,MyISAM不支持。須要注意的是,InnDB行級鎖也不是絕對的,例如mysql執行一個未定範圍的sql時,也仍是會鎖表,例如sql中like的使用

2.效率,明顯MyISAM在插入數據的表現是InnoDB所遠遠不及的,在刪改查,隨着InnoDB的優化,差距漸漸變小

3.行數查詢,InnoDB不保存行數,也就是select的時候,要掃描全表,MyISAM只需讀取保存的行數便可,這也是MyISAM查詢速度快的一個因素。

4.索引,InnoDB會自動建立Auto_Increment類型字段的索引,通常習慣應用於主鍵,即主鍵索引(只包含該字段),而MyISAM能夠和其餘字段建立聯合索引。

除此以外,MyISAM還支持全文索引(FULLTEXT_INDEX),壓縮索引,InnoDB不支持。

備註:MyISAM的索引和數據是分開的,而且索引是有壓縮的,內存使用率就對應提升了很多。能加載更多索引,而Innodb是索引和數據是緊密捆綁的,沒有使用壓縮從而會形成Innodb比MyISAM體積龐大不小。

InnoDB存儲引擎被徹底與MySQL服務器整合,InnoDB存儲引擎爲在主內存中緩存數據和索引而維持它本身的緩衝池。InnoDB存儲它的表&索引在一個表空間中,表空間能夠包含數個文件(或原始磁盤分區)。這與MyISAM表不一樣,好比在MyISAM表中每一個表被存在分離的文件中。InnoDB 表能夠是任何尺寸,即便在文件尺寸被限制爲2GB的操做系統上。

5.服務器數據備份。InnoDB必須導出SQL來備份,LOAD TABLE FROM MASTER操做對InnoDB是不起做用的,解決方法是首先把InnoDB表改爲MyISAM表,導入數據後再改爲InnoDB表,可是對於使用的額外的InnoDB特性(例如外鍵)的表不適用。

備註:並且MyISAM應對錯誤編碼致使的數據恢復速度快。MyISAM的數據是以文件的形式存儲,因此在跨平臺的數據轉移中會很方便。在備份和恢復時可單獨針對某個表進行操做。

InnoDB是拷貝數據文件、備份 binlog,或者用 mysqldump,支持災難恢復(僅需幾分鐘),MyISAM不支持,遇到數據崩潰,基本上很難恢復,因此要常常進行數據備份。

6.鎖的支持。**MyISAM只支持表鎖。InnoDB支持表鎖、行鎖 行鎖大幅度提升了多用戶併發操做的新能。可是InnoDB的行鎖,只是在WHERE的主鍵是有效的,非主鍵的WHERE都會鎖全表的

使用場景建議:

1)可靠性高或者要求事務處理,則使用InnoDB。這個是必須的。

2)表更新和查詢都至關的頻繁,而且表鎖定的機會比較大的狀況指定InnoDB數據引擎的建立。

對比之下,MyISAM的使用場景:

1)作不少count的計算的。如一些日誌,調查的業務表。

2)插入修改不頻繁,查詢很是頻繁的。

MySQL可以容許你在表這一層應用數據庫引擎,因此你能夠只對須要事務處理的表格來進行性能優化,而把不須要事務處理的表格交給更加輕便的MyISAM引擎。對於 MySQL而言,靈活性纔是關鍵。

引擎原理分析

MyISAM索引結構: MyISAM索引用的B+ tree來儲存數據,MyISAM索引的指針指向的是鍵值的地址,地址存儲的是數據。B+Tree的數據域存儲的內容爲實際數據的地址,也就是說它的索引和實際的數據是分開的,只不過是用索引指向了實際的數據,這種索引就是所謂的非彙集索引

主索引以下:

輔助索引以下:

所以,過程爲: MyISAM中索引檢索的算法爲首先按照B+Tree搜索算法搜索索引,若是指定的Key存在,則取出其data域的值,而後以data域的值爲地址,根據data域的值去讀取相應數據記錄。

InnoDB引擎的索引結構:

也是B+Treee索引結構。Innodb的索引文件自己就是數據文件,即B+Tree的數據域存儲的就是實際的數據,這種索引就是彙集索引。這個索引的key就是數據表的主鍵,所以InnoDB表數據文件自己就是主索引。

InnoDB的輔助索引數據域存儲的也是相應記錄主鍵的值而不是地址,因此當以輔助索引查找時,會先根據輔助索引找到主鍵,再根據主鍵索引找到實際的數據。因此Innodb不建議使用過長的主鍵,不然會使輔助索引變得過大。

建議使用自增的字段做爲主鍵,這樣B+Tree的每個結點都會被順序的填滿,而不會頻繁的分裂調整,會有效的提高插入數據的效率。

主索引以下:

輔助索引以下:

上圖,能夠看到葉節點包含了完整的數據記錄。這種索引叫作彙集索引。由於InnoDB的數據文件自己要按主鍵彙集,因此InnoDB要求表必須有主鍵(MyISAM能夠沒有),若是沒有顯式指定,則MySQL系統會自動選擇一個能夠惟一標識數據記錄的列做爲主鍵,若是不存在這種列,則MySQL自動爲InnoDB表生成一個隱含字段做爲主鍵,這個字段長度爲6個字節,類型爲長整形。

並且,與MyISAM索引的不一樣是InnoDB的輔助索引data域存儲相應記錄主鍵的值而不是地址。換句話說,InnoDB的全部輔助索引都引用主鍵做爲data域。

所以,過程爲:將主鍵組織到一棵B+樹中,而行數據就儲存在葉子節點上,若使用」where id = 13」這樣的條件查找主鍵,則按照B+樹的檢索算法便可查找到對應的葉節點,以後得到行數據。若對Name列進行條件搜索,則須要兩個步驟:第一步在輔助索引B+樹中檢索Name,到達其葉子節點獲取對應的主鍵。第二步使用主鍵在主索引B+樹種再執行一次B+樹檢索操做,最終到達葉子節點便可獲取整行數據。

兩種索引數據查找過程以下:

相關文章
相關標籤/搜索