題外話:中華文化博大進深,從學Java到數據庫,無一不體現出同一組件魚和熊掌不可兼得的要義。自然,編程中安全和效率也很難同時做到完美,這一次InnoDB和MyISAM又讓我大開眼界。
好了,Talk is cheap,show you the code:
測試環境:Mysql 5.7.20-log,IDEA 2018
首先創建兩張表: testinnodb,testmyisam,sql如下:

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表數據文件本身就是主索引。【Java高架構師、分布式架構、高可擴展、高性能、高並發、性能優化、Spring boot、Redis、ActiveMQ、Nginx、Mycat、Netty、Jvm大型分布式項目實戰學習架構師視頻免費獲取架構群;855355016】
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+樹檢索操作,最終到達葉子節點即可獲取整行數據。
兩種索引數據查找過程如下:

小禮物走一走,來簡書關注我
作者:Java高級技術
鏈接:https://www.jianshu.com/p/92ba79cbc6a3
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯系作者獲得授權並注明出處。