zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

MySQL中MyISAM和InnoDB

mysql InnoDB MyISAM
2023-09-11 14:16:37 时间

先讲讲MyISAM:

MyISAM 存储引擎是 MySQL 中常见的存储引擎,曾(MySQL 5.1及之前版本)是 MySQL 的默认存储引擎。

MyISAM 是基于 ISAM 存储引擎发展起来的。实际上那会还没有存储引擎的概念,ISAM 只是一种算法,或者说是数据的处理方式。如同 SQL Server/Oracle 这类产品一样,MySQL 对表对象的管理方式只有一种。随着 MySQL 架构的不断发展和演进,最终才引入插件式存储引擎的概念,ISAM 也进化为 MyISAM 并一直作为 MySQL 数据库的默认存储引擎,直到 MySQL 5.5 版本才被 InnoDB 引擎取代了默认存储引擎的地位。

下面主要从优缺点和物理存储等方面来介绍 MyISAM 存储引擎。

优缺点

作为 MySQL 最早的存储引擎之一,MyISAM 有一些已经开发出来很多年的特性,可以满足用户的实际需求。例如全文索引、压缩、空间函数(GIS)等。但 MySQL 官方的重心早就不在 MyISAM 引擎上了,所以近些年来,MyISAM 一直没有很大的改进,也存在着许多的缺陷。

优点
*占用空间小
*访问速度快,对事务完整性没有要求或以 SELECT、INSERT 为主的应用基本上都可以使用这个引擎来创建表
*可以配合锁,实现操作系统下的复制备份
*支持全文检索(InnoDB 在 MySQL 5.6 版本以后也支持全文检索)
*数据紧凑存储,因此可获得更小的索引和更快的全表扫描性能。

1. 加锁与并发

MyISAM 对整张表加锁,而不是针对行。读取时会对需要读到的所有表加共享锁,写入时对表加排他锁。但是在表有读取查询的同时,也可以往表中插入新的记录(这被称为并发插入)。

2. 修复

对于 MyISAM 表,MySQL 可以手工(执行命令 CHECK TABLE tablename)或者自动执行检查和修复(执行命令 REPAIR TABLE tablename)操作,但这里说的修复和事务恢复以及崩溃修复是不同的概念。

另外,如果 MySQL 服务器已经关闭,也可以通过 myisamchk 命令行工具进行检查和修复操作

3. 索引特性

MyISAM 支持以下 3 种类型的索引:

1)B-Tree 索引
B-Tree 索引,顾名思义,就是所有的索引节点都按照 balance tree 的数据结构来存储,所有的索引数据节点都在叶节点。

2)R-Tree 索引
R-Tree 索引的存储方式和 b-tree 索引有一些区别,主要设计用于为存储空间和多维数据的字段做索引,所以对于目前的 MySQL 版本来说,
也仅支持 geometry 类型的字段作索引。
3)Full-text 索引 Full-text 索引就是全文索引,它的存储结构也是 b-tree。主要是为了解决需要用 like 查询时的低效问题。 MyISAM 上面三种索引类型中,最经常使用的就是 B-Tree 索引了,偶尔会使用到 Full-text,但是 R-Tree 索引一般系统中都是很少用到的。
另外 MyISAM 的 B-Tree 索引有一个较大的限制,那就是参与一个索引的所有字段的长度之和不能超过 1000 字节。
缺点
  • 不支持事务的完整性和并发性
  • 不支持行级锁,使用表级锁,并发性差
  • 主机宕机后,MyISAM表易损坏,灾难恢复性不佳
  • 数据库崩溃后无法安全恢复
  • 只缓存索引,数据的缓存是利用操作系统缓冲区来实现的,可能会引发过多的系统调用,且效率不佳

物理存储

MyISAM 存储引擎的表在数据库中被存储成 3 个物理文件,文件名与表名相同。扩展名为 frm、MYD 和 MYI。其中:

  • frm 为扩展名的文件存储表的结构;
  • MYD 为扩展名的文件存储数据,其是 MYData 的缩写;
  • MYI 为扩展名的文件存储索引,其是 MYIndex 的缩写。不管表有多少索引,都是存放在同一个 .MYI 文件中。


MyISAM 类型的数据文件和索引文件可以放置在不同的目录,平均分布 IO,以此来获得更快的速度。

要指定索引文件和数据文件的路径,需要在创建表的时候通过 DATA DIRECTORY 和 INDEX DIRECTORY 语句指定,也就是说不同 MyISAM 表的索引文件和数据文件可以放置到不同的路径下。文件路径需要是绝对路径,并且具有访问权限。

虽然每一个 MyISAM 的表数据都存放在后缀名为 .MYD 的文件中,但是每个文件的存放格式可能并不完全一样。因为 MyISAM 支持 3 种不同的数据存放格式,即静态型、动态型和压缩型。

1)静态型

静态型为 MyISAM 存储引擎的默认存储格式,其字段是固定长度,这样每个记录都是固定长度的,这种存储方式存储非常迅速,容易缓存,出现故障容易恢复。

缺点是占用的空间比动态表多。静态型的表的数据在存储的时候会按照列的宽度定义去补足空格,但是在应用访问的时候并不会得到这些空格,空格在返回给应用之前就被去掉了。

需要注意的是,如果需要保存的内容后面本来就带有空格,那么在返回结果的时候也会被去掉。这一点开发人员在编写程序的时候需要特别注意,因为静态表是默认的存储格式,开发人员可能并没有意识到这一点,从而丢失了尾部的空格。

2)动态型

动态型包含变长字段,记录的长度不是固定的。这样存储的优点是占用的空间相对较少,但是频繁的更新删除记录会产生碎片,需要定期执行 OPTIMIZE TABLE 语句或 myisamchk -r 命令来改善性能,并且出现故障的时候恢复相对比较困难。

3)压缩型

与上面两种格式相比,压缩型的表就显得特殊一些。压缩型的表需要使用 myisampack 工具创建,解压缩则用另外的 myisamchk 命令。压缩表是制度的,不支持添加或修改记录。

压缩表是基于静态或动态格式表的,优点在于占用的磁盘空间非常小,可以减少磁盘 I/O,从而提升查询性能。因为每个记录都是被单独压缩的,所以只有非常小的开支。

理论上,MyISAM 存储引擎的表可以被多个数据库实例同时使用同时操作,但是一般不建议这样做,关于这点,MySQL 官方的用户手册中也有提到,建议尽量不要在多个 mysqld 之间共享 MyISAM 存储文件

如果表在创建并导入数据以后,不会再进行修改操作,这样的表或许适合采用 MyISAM 压缩表。

再讲讲MyISAM与InnoDB 的区别

区别:
1. InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;

2. InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;

3. InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和(主键)索引绑在一起的(表数据文件本身就是按B+Tree组织的一个索引结构),必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。

MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。

也就是说:InnoDB的B+树主键索引的叶子节点就是数据文件,辅助索引的叶子节点是主键的值;而MyISAM的B+树主键索引和辅助索引的叶子节点都是数据文件的地址指针

4. InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快(注意不能加有任何WHERE条件);

那么为什么InnoDB没有了这个变量呢?

因为InnoDB的事务特性,在同一时刻表中的行数对于不同的事务而言是不一样的,因此count统计会计算对于当前事务而言可以统计到的行数,而不是将总行数储存起来方便快速查询。InnoDB会尝试遍历一个尽可能小的索引除非优化器提示使用别的索引。如果二级索引不存在,InnoDB还会尝试去遍历其他聚簇索引。
如果索引并没有完全处于InnoDB维护的缓冲区(Buffer Pool)中,count操作会比较费时。可以建立一个记录总行数的表并让你的程序在INSERT/DELETE时更新对应的数据。和上面提到的问题一样,如果此时存在多个事务的话这种方案也不太好用。如果得到大致的行数值已经足够满足需求可以尝试SHOW TABLE STATUS

5. Innodb不支持全文索引,而MyISAM支持全文索引,在涉及全文索引领域的查询效率上MyISAM速度更快高;PS:5.7以后的InnoDB支持全文索引了

6. MyISAM表格可以被压缩后进行查询操作

7. InnoDB支持表、行(默认)级锁,而MyISAM支持表级锁

InnoDB的行锁是实现在索引上的,而不是锁在物理行记录上。潜台词是,如果访问没有命中索引,也无法使用行锁,将要退化为表锁。

例如:
 
    t_user(uid, uname, age, sex) innodb;
 
    uid PK
    无其他索引
    update t_user set age=10 where uid=1;             命中索引,行锁。
 
    update t_user set age=10 where uid != 1;           未命中索引,表锁。
 
    update t_user set age=10 where name='chackca';    无索引,表锁。

8、InnoDB表必须有唯一索引(如主键)(用户没有指定的话会自己找/生产一个隐藏列Row_id来充当默认主键),而Myisam可以没有

9、Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI

Innodb:frm是表定义文件,ibd是数据文件

Myisam:frm是表定义文件,myd是数据文件,myi是索引文件

如何选择:

1. 是否要支持事务,如果要请选择innodb,如果不需要可以考虑MyISAM;

2. 如果表中绝大多数都只是读查询,可以考虑MyISAM,如果既有读也有写,请使用InnoDB。

3. 系统奔溃后,MyISAM恢复起来更困难,能否接受;

4. MySQL5.5版本开始Innodb已经成为Mysql的默认引擎(之前是MyISAM),说明其优势是有目共睹的,如果你不知道用什么,那就用InnoDB,至少不会差。

InnoDB为什么推荐使用自增ID作为主键?

答:自增ID可以保证每次插入时B+索引是从右边扩展的,可以避免B+树和频繁合并和分裂(对比使用UUID)。如果使用字符串主键和随机主键,会使得数据随机插入,效率比较差。

innodb引擎的4大特性

插入缓冲(insert buffer),二次写(double write),自适应哈希索引(ahi),预读(read ahead)

————————————————
referance:https://blog.csdn.net/qq_35642036/article/details/82820178