千万级MySQL数据库建立索引,提高性能的秘诀( 三 )


存储空间:MyISAM可被压缩,占据的存储空间较小,支持静态表、动态表、压缩表三种不同的存储格式 。InnoDB需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引 。
可移植性、备份及恢复:MyISAM的数据是以文件的形式存储,所以在跨平台的数据转移中会很方便,同时在备份和恢复时也可单独针对某个表进行操作 。InnoDB免费的方案可以是拷贝数据文件、备份 binlog,或者用 mysqldump,在数据量达到几十G的时候就相对痛苦了 。
事务支持:MyISAM强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持 。InnoDB提供事务、外键等高级数据库功能,具有事务提交、回滚和崩溃修复能力 。
AUTO_INCREMENT:在MyISAM中,可以和其他字段一起建立联合索引 。引擎的自动增长列必须是索引,如果是组合索引,自动增长可以不是第一列,它可以根据前面几列进行排序后递增 。InnoDB中必须包含只有该字段的索引,并且引擎的自动增长列必须是索引,如果是组合索引也必须是组合索引的第一列 。
表锁差异:MyISAM只支持表级锁,用户在操作MyISAM表时,select、update、delete和insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据 。InnoDB支持事务和行级锁 。行锁大幅度提高了多用户并发操作的新能,但是InnoDB的行锁,只是在WHERE的主键是有效的,非主键的WHERE都会锁全表的 。
全文索引:MyISAM支持 FULLTEXT类型的全文索引;InnoDB不支持FULLTEXT类型的全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好 。
表主键:MyISAM允许没有任何索引和主键的表存在,索引都是保存行的地址 。对于InnoDB,如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见),数据是主索引的一部分,附加索引保存的是主索引的值 。
表的具体行数:MyISAM保存表的总行数,select count() from table;会直接取出出该值;而InnoDB没有保存表的总行数,如果使用select count() from table;就会遍历整个表,消耗相当大,但是在加了wehre条件后,myisam和innodb处理的方式都一样 。
CURD操作:在MyISAM中,如果执行大量的SELECT,MyISAM是更好的选择 。对于InnoDB,如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表 。DELETE从性能上InnoDB更优,但DELETE FROM table时,InnoDB不会重新建立表,而是一行一行的删除,在innodb上如果要清空保存有大量数据的表,最好使用truncate table这个命令 。
外键:MyISAM不支持外键,而InnoDB支持外键 。
通过上述的分析,基本上可以考虑使用InnoDB来替代MyISAM引擎了,原因是InnoDB自身很多良好的特点,比如事务支持、存储过程、视图、行级锁、外键等等 。尤其在并发很多的情况下,相信InnoDB的表现肯定要比MyISAM强很多 。另外,必须需要注意的是,任何一种表都不是万能的,合适的才是最好的,才能最大的发挥MySQL的性能优势 。如果是不复杂的、非关键的Web应用,还是可以继续考虑MyISAM的,这个具体情况具体考虑 。
MyISAM:不支持事务,不支持外键,表锁;插入数据时锁定整个表,查行数时无需整表扫描 。主索引数据文件和索引文件分离;与主索引无区别;
InnoDB:支持事务,外键,行锁,查表总行数时,全表扫描;主索引的数据文件本身就是索引文件;辅助索引记录主键的值;
 
MySQL锁类型
根据锁的类型分,可以分为共享锁,排他锁,意向共享锁和意向排他锁 。
根据锁的粒度分,又可以分为行锁,表锁 。
对于mysql而言,事务机制更多是靠底层的存储引擎来实现,因此,mysql层面只有表锁,而支持事务的innodb存 储引擎则实现了行锁(记录锁(在行相应的索引记录上的锁)),gap锁(是在索引记录间歇上的锁),next-key锁(是记录锁和在此索引记录之前的gap上的锁的结合) 。Mysql的记录锁实质是索引记录的锁,因为innodb是索引组织表;gap锁是索引记录间隙的锁,这种锁只在RR隔离级别下有效;next-key锁是记录锁加上记录之前gap锁的组合 。mysql通过gap锁和next-key锁实现RR隔离级别 。
说明:对于更新操作(读不上锁),只有走索引才可能上行锁;否则会对聚簇索引的每一行上写锁,实际等同于对表上写锁 。若多个物理记录对应同一个索引,若同时访问,也会出现锁冲突;
当表有多个索引时,不同事务可以用不同的索引锁住不同的行,另外innodb会同时用行锁对数据记录(聚簇索引)加锁 。


推荐阅读