MySQL存储引擎MyISAM与InnoDB两者之前的区别

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: MySQL存储引擎MyISAM与InnoDB两者之前的区别

MySQL的存储引擎,MyISAM与InnoDB是我们最经常使用的存储引擎,我们一起来从性能、存储结构、索引、如何抉择的角度,一起来对比下两者之前的差别。

文中讲解的方法,都是MySQL本身支持的,只是涉及的代码,采用C#作为例子。


1、前期准备

1.1、创建表并插入测试数据


分别创建不同引擎的订单表:trade_myisam、trade_innodb,订单表包含id、订单编号两个字段。

创建InonoDB引擎的订单表SQL代码如下:

CREATE TABLE `trade_innodb` (
  `id` INT(11) NOT NULL,
  `trade_no` INT(11) NOT NULL,
  PRIMARY KEY `id` (`id`),
  INDEX `trade_no` (`trade_no`) USING BTREE
)
COMMENT='订单'
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB
;


创建MyISAM引擎的订单表SQL代码如下:

CREATE TABLE `trade_myisam` (
  `id` INT(11) NOT NULL,
  `trade_no` INT(11) NOT NULL,
  PRIMARY KEY `id` (`id`),
  INDEX `trade_no` (`trade_no`) USING BTREE
)
COMMENT='订单'
COLLATE='utf8_unicode_ci'
ENGINE=MyISAM
;


分别插入10万条测试数据,结果如下:

这里所有的字段,采用的都是Int类型,是为了方便我们,下面使用区间查询,来验证查询速度。


1.2、测试环境

文中测试环境电脑配置如下:

操作系统:Window 10 专业版

CPU:Inter(R) Core(TM) i7-8650U CPU @1.90GHZ 2.11 GHZ

内存:16G

MySQL版本:5.7.26

2、MyISAM与InnoDB性能对比

2.1 验证思路


MyISAM在MySQL 5.5 及之前的版本,MyISAM是默认引擎;InnoDB是专门为处理巨大数据量时的最大性能设计的,现在为MySQL默认引擎。


在MySQL官方文档说明,MyISAM比InnoDB查询快,但很多人都不知道其中的原理。


在探索其中原理之前,我们先验证下查询速度,另外也验证下MyISAM是否真的比InnoDB查询性能好。


在Mysql中,索引分为主键索引和非主键索引,这两种索引都能起到,加快查询速度的作用,但在查询速度上是有区别的,主键索引要快于非主键索引,所以我们从以下两个方面去验证:


1、通过主键查询,MyISAM是否比InnoDB查询快?


2、通过非主键字段查询,MyISAM是否比InnoDB查询快?


具体验证方法为:


1、分别通过id、trade_no查询10000~20000区间的记录,并获得查询所花费时间。


2、循环查询100次,并取得查询耗费时间平均值。


3、通过对比查询耗费时间平均值,来判断性能。

2.2、验证测试

2.2.1、主键查询性能测试

查询主键id在10000~20000区间,查询100次,并统计耗费时间的平均值,C#实现代码如下:

using (var conn = new MySqlConnection(connsql))
{
    conn.Open();
    //查询次数
    var queryTime = 1000;
    //InnoDB数据引擎:主键查询
    //开始时间
    var startTime = DateTime.Now;
    for (var i = 0; i < queryTime; i++)
    {
        //插入
        var sql = "select * from trade_innodb where id>=10000 and id<20000";
        var sqlComm = new MySqlCommand();
        sqlComm.Connection = conn;
        sqlComm.CommandText = sql;
        sqlComm.ExecuteScalar();
        sqlComm.Dispose();
    }
    //完成时间
    var endTime = DateTime.Now;
    //耗时
    var spanTime = (endTime - startTime) * 1.0 / queryTime;
    Console.WriteLine("InnoDB主键查询1000次平均耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");
    //MyISAM数据引擎:主键查询
    //开始时间
    startTime = DateTime.Now;
    for (var i = 0; i < queryTime; i++)
    {
        //插入
        var sql = "select * from trade_myisam where id>=10000 and id<20000";
        var sqlComm = new MySqlCommand();
        sqlComm.Connection = conn;
        sqlComm.CommandText = sql;
        sqlComm.ExecuteScalar();
        sqlComm.Dispose();
    }
    //完成时间
    endTime = DateTime.Now;
    //耗时
    spanTime = (endTime - startTime) * 1.0 / queryTime;
    Console.WriteLine("MyISAM主键查询1000次平均耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");
    conn.Close();
   }

运行结果:

通过上面的图片,可以看到结果:主键查询的方式,MyISAM查询性能比较Innodb快。


2.2.2、非主键查询

查询非主键trade_no在10000~20000区间,查询100次,并统计耗费时间的平均值,C#实现代码如下:

using (var conn = new MySqlConnection(connsql))
{
    conn.Open();
    //查询次数
    var queryTime = 1000;
    //InnoDB数据引擎:非主键查询
    //开始时间
    var startTime = DateTime.Now;
    for (var i = 0; i < queryTime; i++)
    {
        //插入
        var sql = "select * from trade_innodb where trade_no>=10000 and trade_no<20000";
        var sqlComm = new MySqlCommand();
        sqlComm.Connection = conn;
        sqlComm.CommandText = sql;
        sqlComm.ExecuteScalar();
        sqlComm.Dispose();
    }
    //完成时间
    var endTime = DateTime.Now;
    //耗时
    var spanTime = (endTime - startTime) * 1.0 / queryTime;
    Console.WriteLine("InnoDB非主键查询1000次平均耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");
    //MyISAM数据引擎:非主键查询
    //开始时间
    startTime = DateTime.Now;
    for (var i = 0; i < queryTime; i++)
    {
        //插入
        var sql = "select * from trade_myisam where trade_no>=10000 and trade_no<20000";
        var sqlComm = new MySqlCommand();
        sqlComm.Connection = conn;
        sqlComm.CommandText = sql;
        sqlComm.ExecuteScalar();
        sqlComm.Dispose();
    }
    //完成时间
    endTime = DateTime.Now;
    //耗时
    spanTime = (endTime - startTime) * 1.0 / queryTime;
    Console.WriteLine("MyISAM非主键查询1000次平均耗时:" + spanTime.Minutes + "分" + spanTime.Seconds + "秒" + spanTime.Milliseconds + "毫秒");
    conn.Close();
}


运行结果:

通过上面的图片,可以看到结果:非主键查询的方式,MyISAM查询性能比较Innodb快。


2.3 验证结论

通过我们的验证来看,不管是主键还是非主键查询,MyISAM查询性能确实比较Innodb快。

3、MyISAM与InnoDB区别

从上面的验证测试结果看,MyISAM与InnoDB查询速度是不一样,下面我们一起来看看它们的区别。


3.1、维护区别


通过上面表格对比,InnoDB在做SELECT的时候,要维护的东西比MYISAM引擎多很多,影响查询速度有:


1)数据块,InnoDB要缓存,MyISAM只缓存索引块,  这中间还有换进换出的减少;


2)InnoDB寻址要映射到块,再到行,MyISAM记录的直接是文件的OFFSET,定位比InnoDB要快;


3)InnoDB还需要维护MVCC一致;虽然你的场景没有,但他还是需要去检查和维护


MVCC (Multi-Version Concurrency Control)多版本并发控制 。

3.2、索引区别

MyISAM与InnoDB索引存储方式也是不一样的(关于索引的使用请查看《细说MySql索引原理》)。


InnoDB表是根据主键进行展开的 B+tree 的聚集索引。MyISAM则非聚集型索引,MyISAM存储会有两个文件,一个是索引文件,另外一个是数据文件,其中索引文件中的索引指向数据文件中的表数据。


聚集型索引并不是一种单独的索引类型,而是一种存储方式,InnoDB 聚集型索引实际上是在同一结构中保存了 B+tree 索引和数据行。当有聚簇索引时,它的索引实际放在叶子页中。


下面我们通过2张图,我们就能直观看到这两个引擎,索引结构的区别:


3.3、MVCC的维护


InnoDB引擎还有需要实现MVCC,这里面也是损耗一定的性能的。Innodb是通过每一行记录有2个额外的隐藏值来实现,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删除)。


但是InnoDB并不存储这些事件发生时的实际时间,相反它只存储这些事件发生时的系统版本号。这是一个随着事务的创建而不断增长的数字。每个事务在事务开始时会记录它自己的系统版本号。每个查询必须去检查每行数据的版本号与事务的版本号是否相同。


3.4、其他差别

1、InnoDB支持事务,MyISAM不支持,针对数据的增删改如果出错,采用InnoDB引擎,MySQL会自动帮我们维护,而MyISAM不会;


2、InnoDB支持外键,MyISAM不支持;


3、InnoDB不支持FullText类型的全文索引;


4、InnoDB是不保存表的行数,如果要返回表的总行数,InnoDB需要扫描一遍表来统计总数,但MyISAM不需要,只需返回已经存储好的行数;


5、删除整个表数据,InnoDB是一行一行的删除,效率非常慢。MyISAM则会重建表。而采用TRUNCATE 操作而不受影响;


6、MyISAM是表锁,所以对于一些高并发的操作,容易导致整个表卡主,性能非常慢;而InnoDB采用的是行锁,但如果更新操作,没有使用索引,依然会触发表锁。

4、MyISAM与InnoDB使用的选择


从上面的对比看,InnoDB支持一些关系数据库的高级功能,如事务功能和行级锁,MyISAM不支持。MyISAM的性能更优,占用的存储空间少。那关于这两种引擎我们如何选择呢。


先抛开性能的差别,两者之间最大的差别就是事务的区别,在实际开发中,如果我们选择MyISAM,我们就要在业务代码中自己去维护,这块业务实现是非常麻烦的,并且只要涉及插入、更新、删除的地方都要维护。


从上面性能对比看,这两个引擎查询性能差别还是比较小的,平常在我们业务系统中,InnoDB数据引擎完全可以满足我们的需求,完全没必要为了这点性能,给我们带来更多的工作量。


MyISAM引擎不需要去维护索引文件,所以在相同的数据量下,MyISAM引擎占用的空间是更小的,所以MyISAM特别适合用于存储数据仓库,特别是较多查询、少量更新的业务场景中,比如系统日志。

5、总结


通过我们的验证来看,不管是主键还是非主键查询,MyISAM查询性能确实比较InnoDB快,但两者差别不是很大,我们在开发中,默认采用InnoDB就可以,这样开发工作量比较少,可以提升我们的开发效率,针对一些有存储空间要求的,再来考虑采用MyISAM。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
8天前
|
存储 缓存 关系型数据库
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
MySQL的存储引擎是其核心组件之一,负责数据的存储、索引和检索。不同的存储引擎具有不同的功能和特性,可以根据业务需求 选择合适的引擎。本文详细介绍了MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案。
【MySQL进阶篇】存储引擎(MySQL体系结构、InnoDB、MyISAM、Memory区别及特点、存储引擎的选择方案)
|
13天前
|
存储 关系型数据库 MySQL
“COUNT(*) MyISAM比InnoDB更快”是误解
在我印象中,MyISAM的查询速度比InnoDB快,但根据MySQL官网文章,从5.7版本开始,InnoDB性能大幅提升,在8.0中持续优化。InnoDB提供更好的性能、可靠性和可扩展性,支持ACID事务、行级锁定、崩溃恢复等特性,成为现代应用的默认选择。尤其在高可用性和灾难恢复方面,InnoDB是唯一选择。云服务也普遍不支持MyISAM。因此,建议使用MyISAM的用户尽早迁移到InnoDB以获得更佳性能和可靠性。
40 11
|
13天前
|
存储 关系型数据库 MySQL
MySQL存储引擎详述:InnoDB为何胜出?
MySQL 是最流行的开源关系型数据库之一,其存储引擎设计是其高效灵活的关键。InnoDB 作为默认存储引擎,支持事务、行级锁和外键约束,适用于高并发读写和数据完整性要求高的场景;而 MyISAM 不支持事务,适合读密集且对事务要求不高的应用。根据不同需求选择合适的存储引擎至关重要,官方推荐大多数场景使用 InnoDB。
56 7
|
22天前
|
存储 关系型数据库 MySQL
Mysql索引:深入理解InnoDb聚集索引与MyisAm非聚集索引
通过本文的介绍,希望您能深入理解InnoDB聚集索引与MyISAM非聚集索引的概念、结构和应用场景,从而在实际工作中灵活运用这些知识,优化数据库性能。
98 7
|
10天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
35 3
|
10天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
37 3
|
10天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE &#39;log_%&#39;;`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
51 2
|
24天前
|
关系型数据库 MySQL 数据库
Python处理数据库:MySQL与SQLite详解 | python小知识
本文详细介绍了如何使用Python操作MySQL和SQLite数据库,包括安装必要的库、连接数据库、执行增删改查等基本操作,适合初学者快速上手。
167 15
|
17天前
|
SQL 关系型数据库 MySQL
数据库数据恢复—Mysql数据库表记录丢失的数据恢复方案
Mysql数据库故障: Mysql数据库表记录丢失。 Mysql数据库故障表现: 1、Mysql数据库表中无任何数据或只有部分数据。 2、客户端无法查询到完整的信息。
|
24天前
|
关系型数据库 MySQL 数据库
数据库数据恢复—MYSQL数据库文件损坏的数据恢复案例
mysql数据库文件ibdata1、MYI、MYD损坏。 故障表现:1、数据库无法进行查询等操作;2、使用mysqlcheck和myisamchk无法修复数据库。