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 一直没有很大的改进,也存在着许多的缺陷。
MyISAM 对整张表加锁,而不是针对行。读取时会对需要读到的所有表加共享锁,写入时对表加排他锁。但是在表有读取查询的同时,也可以往表中插入新的记录(这被称为并发插入)。
对于 MyISAM 表,MySQL 可以手工(执行命令 CHECK TABLE tablename)或者自动执行检查和修复(执行命令 REPAIR TABLE tablename)操作,但这里说的修复和事务恢复以及崩溃修复是不同的概念。
另外,如果 MySQL 服务器已经关闭,也可以通过 myisamchk 命令行工具进行检查和修复操作。
MyISAM 支持以下 3 种类型的索引:
B-Tree 索引,顾名思义,就是所有的索引节点都按照 balance tree 的数据结构来存储,所有的索引数据节点都在叶节点。
R-Tree 索引的存储方式和 b-tree 索引有一些区别,主要设计用于为存储空间和多维数据的字段做索引,所以对于目前的 MySQL 版本来说,也仅支持 geometry 类型的字段作索引。
Full-text 索引就是全文索引,它的存储结构也是 b-tree。主要是为了解决需要用 like 查询时的低效问题。
MyISAM 上面三种索引类型中,最经常使用的就是 B-Tree 索引了,偶尔会使用到 Full-text,但是 R-Tree 索引一般系统中都是很少用到的。另外 MyISAM 的 B-Tree 索引有一个较大的限制,那就是参与一个索引的所有字段的长度之和不能超过 1000 字节。
MyISAM 存储引擎的表在数据库中被存储成 3 个物理文件,文件名与表名相同。扩展名为 frm、MYD 和 MYI。其中:
MyISAM 类型的数据文件和索引文件可以放置在不同的目录,平均分布 IO,以此来获得更快的速度。
要指定索引文件和数据文件的路径,需要在创建表的时候通过 DATA DIRECTORY 和 INDEX DIRECTORY 语句指定,也就是说不同 MyISAM 表的索引文件和数据文件可以放置到不同的路径下。文件路径需要是绝对路径,并且具有访问权限。
虽然每一个 MyISAM 的表数据都存放在后缀名为 .MYD 的文件中,但是每个文件的存放格式可能并不完全一样。因为 MyISAM 支持 3 种不同的数据存放格式,即静态型、动态型和压缩型。
静态型为 MyISAM 存储引擎的默认存储格式,其字段是固定长度,这样每个记录都是固定长度的,这种存储方式存储非常迅速,容易缓存,出现故障容易恢复。缺点是占用的空间比动态表多。静态型的表的数据在存储的时候会按照列的宽度定义去补足空格,但是在应用访问的时候并不会得到这些空格,空格在返回给应用之前就被去掉了。
需要注意的是,如果需要保存的内容后面本来就带有空格,那么在返回结果的时候也会被去掉。这一点开发人员在编写程序的时候需要特别注意,因为静态表是默认的存储格式,开发人员可能并没有意识到这一点,从而丢失了尾部的空格。
动态型包含变长字段,记录的长度不是固定的。这样存储的优点是占用的空间相对较少,但是频繁的更新删除记录会产生碎片,需要定期执行 OPTIMIZE TABLE 语句或 myisamchk -r 命令来改善性能,并且出现故障的时候恢复相对比较困难。
与上面两种格式相比,压缩型的表就显得特殊一些。压缩型的表需要使用 myisampack 工具创建,解压缩则用另外的 myisamchk 命令。压缩表是制度的,不支持添加或修改记录。
压缩表是基于静态或动态格式表的,优点在于占用的磁盘空间非常小,可以减少磁盘 I/O,从而提升查询性能。因为每个记录都是被单独压缩的,所以只有非常小的开支。
理论上,MyISAM 存储引擎的表可以被多个数据库实例同时使用同时操作,但是一般不建议这样做,关于这点,MySQL 官方的用户手册中也有提到,建议尽量不要在多个 mysqld 之间共享 MyISAM 存储文件。
如果表在创建并导入数据以后,不会再进行修改操作,这样的表或许适合采用 MyISAM 压缩表。