这个问题想必大家都被问过无数次。今天来总结一下。
1.myisam:
文件结构:frm,myi,myd
frm是文件信息,myi是索引文件,myd是数据文件。(5.6之前只有myisam支持全文检索。Innodb不支持全文检索,5.6以后开始支持。)
myisam引擎支持的表锁,这样就造成myisam对并发的支持非常差。如果对一张表的数据进行修改,整张表都会被锁定,其他进程只能等待该进程释放后才能对该表进行读和写。
select和Insert较innodb来说快。
引用两篇性能测试文章
2012年
http://www.4wei.cn/archives/1001855
2014年
http://xmgu2008.blog.163.com/blog/static/139122380201402492349491/
从第一篇文章中可以看到,innodb因为受 innodb_flush_log_at_trx_commit 这个选项的影响,所以自动提交和手动提交性能相去甚远。
取select count(*)极快,因为myisam表都会有一个叫表状态的内存空间。这个表的总记录数,以及修改时间和表的长度等等关键数据都是存在一个单独的内存块里面的,当你发起select count(*)这样的请求,Myisam引擎就不会真的去扫描标表行数了。直接从内存中把该变量读出来。但是如果你加了一个where条件,而且这个条件的字段不是索引的话,他依然会去扫描表的每一行。
2.Indodb
2.1事物支持
Indodb最重要的一条特性就是支持事务。如果你的业务模型需要原子性的sql操作,需要保证高并发下的数据一致性,就要用到事物。
2.2行级锁定
对并发的支持较好,只锁定表中需要修改的那一行,update的速度比myisam引擎速度要快。但是比教消耗资源
3.索引与数据存储结构对比
3.1.myisam:
primary(主键索引)与secondary(二级索引)结构相同,每条索引记录保存后面的指针(myisam的记录是一行行的,如果你的记录有10万行,那么myd这个文件就有10万行,每一行在哪个位置就是记录的指针)
数据都是顺序插入的。
每次Insert都是在数据最后一行插入。那么问题来了,如果我们普通Insert是没有问题,如果去修改一个变长字段,比如已经有了一百行,需要去修改第一行,第一行原来有一个名称是姓名,这个字段是变长的,原来是varchar这种类型,原先只写了10个字节,myisam就用10个字节的空间去存储,现在要把它写成20个字节,把一个行变成一个二进制流来讲,前几十个字节代表第一行,你想把第一行变成更多的字节,那它原来的空间就不能存储了那这个时候,myisam引擎就会再后面追加一个新行,可能其他字段不变,只把你新的二十个字节的姓名写到这个表的最后面,那这个时候,记录这条记录指针的位置已经变了,那这个时候就需要去修改跟这条记录相关的所有索引后面的记录。来保证索引还能指向正确的位置。所以说,你频繁去更新Myisam表变长字段的话,那实际上是很慢的。
Innodb
innodb用的是聚簇索引。聚簇索引的主键用的是自增的id为准,mysiam的主键可以用一个甚至多个字段或者一个字符串当做主键,innodb则是不可以的,innodb只能用自增的数字作为主键,按主键的顺序去存放索引和数据。Innodb
使用b+树去排列,左边比右边的小,通常他的主键和数据是存放在一起的,使用连续的一段空间。你去写一个新的数据的时候,比如写到5,他可能在某个节点的左边子节点,写6的时候,变成右边的子节点,按这样的顺序去写,和myisam不同,根据某一行去追加。innodb的secondary(二级索引)保存的是主键id,因此数据变动时不需要修改索引。