写在最前:
本文参考自juejin.cn/post/685003…
存储引擎
常见的存储引擎就 InnoDB、MyISAM、Memory、NDB。InnoDB 现在是 MySQL 默认的存储引擎,支持事务、行级锁定和外键。本文重点对比介绍InnoDB和MyISAM。
在 MySQL中建立一张数据表时,在其对应的数据库目录下都有对应表的 .frm 文件,.frm 文件是用来保存每个数据表的元数据(meta)信息,包括表结构的定义等,任何存储引擎的数据表都必须有.frm文件,命名方式为 数据表名.frm。
MyISAM 物理文件结构为:
- frm文件:与表相关的元数据信息都存放在frm文件,包括表结构的定义信息等
- MYD (MYData) 文件:MyISAM 存储引擎专用,用于存储MyISAM 表的数据
- MYI (MYIndex)文件:MyISAM 存储引擎专用,用于存储MyISAM 表的索引相关信息
InnoDB 物理文件结构为:
- frm 文件:与表相关的元数据信息都存放在frm文件,包括表结构的定义信息等
- ibd (或ibdata)文件: 这两种文件都是存放 InnoDB 数据的文件,之所以有两种文件形式存放 InnoDB 的数据,是因为 InnoDB 的数据存储方式能够通过配置来决定是使用共享表空间存放存储数据,还是用独享表空间存放存储数据。
两大引擎的区别:
- InnoDB 支持事务,MyISAM 不支持事务。这是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一
- InnoDB 支持外键,而 MyISAM 不支持。对一个包含外键的 InnoDB 表转为 MYISAM 会失败
- InnoDB 是聚簇索引,MyISAM 是非聚簇索引。聚簇索引的数据存放在主键索引的叶子节点上,因此 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大;而 MyISAM 是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的
- InnoDB 不保存表的具体行数,执行select count(*) from table 时需要全表扫描。而 MyISAM 用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快
- InnoDB 最小的锁粒度是行锁,MyISAM 最小的锁粒度是表锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,因此并发访问受限。这也是 MySQL 将默认存储引擎从 MyISAM 变成 InnoDB 的重要原因之一
- MyISAM只缓存索引,不缓存真实数据;InnoDB不仅缓存索引还要缓存真实数据,对内存要求较高,而且内存大小对性能有决定性的影响
问题:
一张表,里面有ID自增主键,当insert了17条记录之后,删除了第15,16,17条记录,再把Mysql重启,再insert一条记录,这条记录的ID是18还>是15?
如果表的类型是MyISAM,那么是18。因为MyISAM表会把自增主键的最大ID 记录到数据文件中,重启MySQL自增主键的最大ID也不会丢失; 如果表的类型是InnoDB,那么是15。因为InnoDB 表只是把自增主键的最大ID记录到内存中,所以重启数据库然后对表进行操作,会导致最大ID丢失。
哪个存储引擎执行 select count(*) 更快,为什么?
MyISAM更快,因为MyISAM内部维护了一个计数器,可以直接调取。
在 MyISAM 存储引擎中,把表的总行数存储在磁盘上,当执行 select count(*) from t 时,直接返回总数据。
在 InnoDB 存储引擎中,跟 MyISAM 不一样,没有将总行数存储在磁盘上,当执行 select count(*) from t 时,会先把数据读出来,一行一行的累加,最后返回总数量。
补充:
InnoDB 在做 SELECT 的时候,要维护的东西比 MYISAM 引擎多很多。
1、InnoDB寻址映射到块,再到行,MyISAM记录文件的OFFSET,定位比InnoDB快。
2、InnoDB还需要维护MVCC一致。
InnoDB:通过为每一行记录添加两个额外的隐藏的值来实现 MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删除)。但是 InnoDB 并不存储这些事件发生时的实际时间,相反它只存储这些事件发生时的系统版本号。这是一个随着事务的创建而不断增长的数字。每个事务在事务开始时会记录它自己的系统版本号。每个查询必须去检查每行数据的版本号与事务的版本号是否相同。让我们来看看当隔离级别是 REPEATABLEREAD 时这种策略是如何应用到特定的操作的:
1、当每行数据的版本号与事务的版本号一致时,才会命中查询
2、该行数据的删除版本必须是未定义的或比事务版本大,意味着在事务开始前这行数据没有被删除。
数据类型
主要分为五大类:整数类型、浮点数类型、字符串类型、日期类型、其他数据类型。
CHAR 和 VARCHAR 的区别?
相同点:
1、char(n),varchar(n)中的n都代表字符的个数
2、超过char,varchar最大长度n的限制后,字符串会被截断。
不同点:
1、char不论实际存储的字符数都会占用n个字符的空间,而varchar只会占用实际字符应该占用的字节空间加1(实际长度length,0<=length<255)或加2(length>255)。因为varchar保存数据时除了要保存字符串之外还会加一个字节来记录长度(如果列声明长度大于255则使用两个字节来保存长度)。
2、能存储的最大空间限制不一样:char的存储上限为255字节。
3、char在存储时会截断尾部的空格,而varchar不会。
CHAR 和 VARCHAR 的区别?
BLOB是一个二进制对象,可以容纳可变数量的数据。有四种类型的BLOB:TINYBLOB、BLOB、MEDIUMBLO和 LONGBLOB。
TEXT是一个不区分大小写的BLOB。四种TEXT类型:TINYTEXT、TEXT、MEDIUMTEXT 和 LONGTEXT。
BLOB 保存二进制数据,TEXT 保存字符数据。