孙宇的技术专栏 大数据/机器学习

MySQL 存储引擎

2013-06-24

阅读:


MyISAM

系统默认的引擎。在性能和牲间的平衡较好。不支持行级锁和事务。

MyISAM 将表存储为两个文件:数据文件(后缀是 .MYD)和索引文件(后缀是 .MYI),同时还有一个 .frm 文件保存表的定义。它的存储格式是平台通用的,也就是说可以在不同架构的服务器上直接拷贝文件进行数据库的复制。如可以将 Windows 上的文件直接复制到 Linux 上进行数据库备份,还原。

MyISAM 表可以包括动态行(一行数据的长度不固定,如使用 text, blob 类型等)和静态行(每一行的长度固定)。可以在建表时定义。如:

create table mytable (a integer not null primary key, b char(18) not null) max_rows = 1000000000 avg_row_length = 32;

在上面的例子中,表的最大行是 1000000000, 平均一行长 32. 也就是说为这个表分配了 1000000000 * 32 = 32G 的容量。MySQL 实际给它分配了多少呢:

show table status like 'mytable' \G
*************************** 1. row ***************************
	           Name: mytable
	         Engine: MyISAM
	        Version: 10
	     Row_format: Fixed
	           Rows: 0
	 Avg_row_length: 0
	    Data_length: 0
	Max_data_length: 98784247807
	   Index_length: 1024
	      Data_free: 0
	 Auto_increment: NULL
	    Create_time: 2013-06-23 08:00:04
	    Update_time: 2013-06-23 08:00:04
	     Check_time: NULL
	      Collation: utf8_general_ci
	       Checksum: NULL
	 Create_options: max_rows = 1000000000 avg_row_length = 32
	        Comment: 

可以看出,实际上该表可以使用的空间是 91G。当然,建表后可以通过 Alter table 来改变这些参数,但这将引发整个表和所有相关索引的重写,会非常耗时。

MyISAM 是对整个表进行加锁,读取时,可以获得所有表上的共享锁(读锁),而写入程序获得排它锁(写锁)。

MyISAM 可以支持对表的自动检查和修复。同时还可以手动,使用 check table mytable, 和 repair table mytable; 检查表中错误并修复。在离线状态下还可以使用 myisamchk 进行检查和修复(http://blog.sina.com.cn/s/blog_5f54f0be01017ojv.html)

MyISAM 可以使用 myisampack 对表数据进行压缩打包。打包后,表里数据只能用来读取,不能修改。除非解压,修改后再重新打包。压缩后的表占用磁盘空间小,查询时磁盘寻道时间大大缩短,查询效率会更高。

InnoDB 引擎

专为事务处理设计的一个引擎。特别用来处理大量简单的,一般不需要回滚的事务。它的性能及崩溃后自动恢复的特性让它很受欢迎。

InnoDB 将所有数据存储在一个或几个数据文件中,不象 MyISAM 一样每个表存储为两个文件。现在的 MySQL 也支持这种形式了。

InnoDB 不能根据排序创建索引,而 MyISAM 支持,因为,InnoDB 在查询和创建索引时要比 MyISAM 慢许多。而且,任何改变 InnoDB 表结构的操作都会导致整个表的重建,以及索引的重建。

InnoDB 使用MVCC机制获取高并发性能。它默认的隔离级别是 repeatable read, 同时它使用 “间隙锁” 策略防止幻读: 不仅对查询中读取的行加锁,还对索引结构中的间隙加锁。

如:select * from emp where empid > 100 ;这里会对 empid 大于 100 的所有记录加锁,如果记录有 10 条,则会对该 10 条记录加锁。同时,对索引结构加锁,意思就是,如果要往里面插入 empid 大于 100 的值,或者将其它记录的 empid 改成大于 100 也是不允许的。

InnoDB 使用聚集索引(B+Tree)。它提供一种非常快速的主键查找性能。不过,它的非主键索引也会包含主键列,所以要把主键定义的小一些。

Blackhole 引擎

该引擎没有任何存储机制,它会丢弃所有的 insert 操作不存储任何数据。不过如果开启了 binlog, 它会记录这些操作。所以,该引擎可以用在集群中的主从复制。

Memory 引擎

如果想获得更高的访问性能,且数据是永不改变的,而且重启后不需要保留。则可以使用内存表。它要比 MyISAM 快一个数量级。但重启后,表结构保留,但数据丢失。通常用来:一些常量表,用来查找或映射。如邮编等。缓存数据分析中的中间结果

Archive引擎

只支持 select 和 insert 操作。它会利用 zlib 对行进行压缩,所以比 MyISAM 有的磁盘 I/O 更少。但每次 select 查询都要进行全表扫描,所以 Archive 表适合日志和数据采集类应用,这类应用做数据分析时往往需要全表扫描。

引擎选择

如果要用到事务, 选 InnoDB 可行。如果只是 select 和 insert ,MyISAM 即可。如果两进行混合,则要选择有行级锁的引擎。

另外,尽量不要在一个库中用多种引擎。这会让备份和性能调整变得复杂。

MyISAM 比 InnoDB 更容易崩溃,而且崩溃后恢复需要的时候更长。所以,有些时候不需要事务,也选择 InnoDB。

MyISAM 支持全文索引。不过也是可以用 InnoDB + Sphinx 实现。

所以,还是直接使用 InnoDB 吧。

日志型应用

如果需要将一个应用的日志,保存到DB中。如 Nginx, Apache 的日志入库。这需要较快的插入速度,这时候可以使用 MyISAM 或 Archive。

如果需要对日志进行分析,而怕对插入造成影响,可以实现主从结构,在主机上插入,在备机上进行查询。或者在库中按年/月进行分表,查询分析的时候可降低对当前要进行插入操作的表进行的查询量。

表引擎转换

Alter table

alter table mytable type = InnoDB;

这种方式可以适用任何引擎,但弊端就是执行时间长,MySQL 会按行将数据从原表复制到一张新表中,复制期间可能会消耗系统所有的I/O能力,同时会在原表上加上读锁。

转换表后,将会失去原引擎的一些特性。比如,将 InnoDB 转换成 MyISAM 然后再转换回 InnoDB, 原表上的外键将丢失。

导出和导入

为了更好控制转换过程,可以使用 mysqldump 将数据导出到文件中,然后修改文件中 create table 的存储引擎。

创建与查询

如果数据量不大,可以用如下办法:

create table innotable like myisam_table;
alter table innotable engin=InnoDB;
insert into innotable select * from myisam_table;

如果数据量大,可以分批。一次 insert 一部分。


上一篇 MySQL 基础架构

下一篇 MySQL 索引

评论

文章