高性能MySQL(3th)(第一章 MySQL概述) —— 04 InnoDB和MyISAM
一 InnoDB和MyISAM存储方式
聚簇 VS 非聚簇
InnoDB采用聚簇索引的方式存储数据,即主键索引(若没有设置unique索引则InnoDB会默认给主键创建索引)和数据一起存储,或者说,表中的数据是在内存中是按照主键索引的递增顺序组织存储的。对于InnoDB,一条sql如果筛选条件利用了主键索引,则InnoDB会直接查询数据文件,在叶子节点即可拿到数据。
而MyISAM则采用了非聚簇索引的方式,将原始数据和索引(任何)分为不同的文件独立存储,一条sql不管筛选条件利用了什么索引,MyISAM都要先查索引文件,再回数据文件相应位置取数据。
为了更加深入理解,想一下InnoDB下为一张表添加索引(非主键索引),此时这个索引文件必然是单独存储的,此时索引和数据就是独立存储的。一般情况下,一条sql如果筛选条件利用了该索引,则InnoDB会先查索引文件,拿到该符合条件记录的id(主键)后,根据id再回数据文件进行一次select where id = xxx。
但是,如果建立的是组合索引(叶子节点不仅有id,还有组合索引的这几列数据),查询也成功地进行了覆盖查询,则直接拿着叶子上的列值返回,不用回主表查询了。
这里也可以看到,InnoDB的索引的B+树的叶子上存储的是该条件下的记录在主数据文件中的内存地址,而InnoDB索引的B+树叶子上存储的要么是完整记录行(主键索引),要么建立该索引使用的列值+主键id(这也提示我们不能InnoDB下不能加你个主键设置得过大)。
上面说的只是逻辑上的概念,实际在实现中,MyISAM有三个文件:表结构定义文件,数据文件,索引文件。
MyISAM表是保存成文件的形式,在跨平台的数据转移中使用MyISAM存储会省去不少的麻烦。
InnoDB要分情况讨论,表结构定义文件 + 数据索引文件
二 主键,外键
InnoDB必须要有主键,MyISAM可以没有,理由也很清楚:InnoDB的数据必须要按照主键索引组织存储,InnoDB下如果没有设定主键或者非空唯一索引,其会自动生成一个6字节的主键(用户不可见)。
前者支持外键,后者不支持。
三 事务,锁粒度
InnoDB支持外键,事务,支持行级锁(默认锁级别),MyISAM不支持外键,事务,只支持表级锁。
四 数据压缩,count
对于只读的表,MyISAM可以使用myisam命令进行数据压缩,更加节省空间;专门的变量存储当前表的记录数目,即count (*)是常数级别的,这两点InnoDB都没有,count(*)要扫描全表。
五 并发场景下怎么选择
先给结论:select和update时,MyISAM更快。
MySQL 中 MyISAM 中的查询为什么比 InnoDB 快
总结一下即;
① 非主键索引时,InnoDB要走2次B+树,MyISAM只有一次。
② 查询InnoDB的主表(不管使用的索引是不是主键索引,最后一步都要回主表,走主键索引),必须要进行大量的I/O将磁盘中的数据调入内存。
而对于这两点,MyISAM都不存在,由于索引和文件是独立存储的,不管利用了什么索引,MyISAM只需要先查索引文件(很小,一次性调用内存),找到叶子上对应的物理地址后,去数据文件中拿数据即可。可以说,总是常数级别的。
③ InnoDB要维护MVCC,虽然select不用维护主键和B+树,但是对于每一行的是否符合条件的判断时都要检查MVCC的创建版本号和删除版本号,至少保证:
A.当前事务的版本号 > 该行的创建版本号——该行已经被创建,并且被其他事务修改;
B.当前事务的版本号 < 该行的删除版本号——操作时,该行还未被删除。
很明显,这些原因会导致InnoDB会MyISAM查询慢。
这也引出一个应用场景,在做读写分离时,InnoDB做主服务器,负责写,读可以负责也可以不负责;MyISAM作从服务器,只负责读。
那么至于update呢?
????
六 Memory引擎