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+树检索操做,最终到达叶子节点便可获取整行数据。

两种索引数据查找过程以下:

相关文章
相关标签/搜索