言:
之前简单介绍过 MySQL 常用的存储引擎,今天对两个主流的存储简单分析下差异,书上没有参考的笔试题解答注解;
差异:
MyISAM 只支持表锁,不支持事务,表损坏率较高。较老的存储引擎。
它分为2种类型的文件:以 MYD 作为后缀名的数据文件和以 MYI 作为后缀名的索引文件。 MyISAM 读写并发不如 InnoDB,适用于INSERT较多的场景,且支持直接复制文件,用以备份数据, 是 MySQL 公司开发的,物理文件主要有数据文件,日志文件和索引文件,并且这三个文件是单独存在。 InnoDB 支持行锁,支持事务,支持行级锁,Crash(崩溃)后具有 Revcover(还原)机制, 只有 ibd 文件,分为数据区和索引区,有较好的读写并发能力,但做 COUNT 运算时相当消耗CPU, 是 InnoDB 公司开发的。物理文件有日志文件,数据文件和索引文件。 其中,索引文件和数据文件是放在一个目录下,可以设置共享文件、独享文件两种格式。PS:help_topic MyISAM 表、innerdb InnoDB 表;
MyISAM |
InnoDB |
|
构成上的区别 |
每个MyISAM在磁盘上存储成三个文件。 每一个文件的名字就是表的名字,文件名都和表名相同, 扩展名指出文件类型。
表定义的扩展名为.frm(frame,存储表定义); 数据文件的扩展名为.MYD(MYData,存储数据); 索引文件的扩展名是.MYI(MYIndex,存储索引);
数据文件和索引文件可以放置在不同的目录下, 平均分布I/O,获得更快的速度。
|
只有ibd文件,分为数据区和索引区,有较好的读写并发能力。
物理文件有:日志文件、数据文件和索引文件。 其中,索引文件和数据文件是放在一个目录下,可以设置共享文件与独享文件两种格式。 基于磁盘的资源是 InnoDB 表空间数据文件和它的日志文件, InnoDB 表的大小只受限于操作系统文件的大小,一般为2GB(单个文件)。
InnoDB 存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。 但是对比 MyISAM 的存储引擎,InnoDB 写的处理效率差一些, 并且会占用更多的磁盘空间以保留数据和索引。 |
事务处理上方面 |
MyISAM类型的表强调的是性能,其执行速度比InnoDB类型更快, 但是不提供事务支持。
|
InnoDB提供事务支持事务、外键等高级数据库功能。
|
SELECTUPDATEINSERTDELETE | 如果执行大量的 SELECT,那么 MyISAM 是更好的选择。 |
(1)如果执行大量的INSERT或UPDATE,那么出于性能方面的考虑,应该使用InnoDB表。 (2)当执行DELETE FROM table时,InnoDB不会重建表,而是一行一行地删除。 (3)LOAD TABLE FROM MASTER 操作对 InnoDB 是不起作用的, 解决方法是首先把 InnoDB 表改成 MyISAM 表,导入数据后再改成 InnoDB 表, 但是对于使用的额外的 InnoDB 特性(例如外键)的表不适用。 |
清空表 |
MyISAM 会重建表。
|
InnoDB 是一行一行地删除,效率非常慢。
|
对AUTO_INCREMENT列的操作 |
MyISAM 为 INSERT 和 UPDATE 操作自动更新这一列。 AUTO_INCREMENT 值可用 ALTER TABLE 来重置。 对于AUTO_INCREMENT类型的字段,InnoDB中必须包含只有该字段的索引,但是在MyISAM表中,可以和其它字段一起建立联合索引。
|
如果为一个表指定AUTO_INCREMENT列, 那么在数据字典里的InnoDB表句柄包含一个名为自动增长计数器的计数器, 它被用在为该列赋新值,自动增长计数器仅被存储在主内存中,而不是存在磁盘上。 InnoDB中必须包含只有该字段的索引。
|
表的行数 |
当执行SQL语句“SELECT COUNT(*) FROM TABLE”时, MyISAM只是简单地读出保存好的行数,需要注意的是, 当COUNT(*)语句包含WHERE条件时, MyISAM和InnoDB的操作是一样的。
|
InnoDB中不保存表的具体行数,也就是说, 当执行SELECT COUNT(*) FROM TABLE时,InnoDB要扫描一遍整个表来计算行数。
|
锁 |
表级锁定(更新时锁定整个表):其锁定机制是表级索引, 这虽然可以让锁定的实现成本很小,但是也同时大大降低了其并发性能。 不支持行级锁,只支持并发插入的表锁,主要用于高负载的SELECT。
|
提供行级锁(locking on row level), 提供与 Oracle 类型一致的不加锁读取(non-locking read), 另外,InnoDB 表的行锁也不是绝对的, 如果在执行一个 SQL 语句时 MySQL 不能确定要扫描的范围, 那么 InnoDB 表同样会锁全表, 例如 UPDATE TABLE T_TEST_LHR SET NUM=1 WHERE NAME LIKE "%LHR%"。
|