1.3 MySQL存储引擎
通过1.2节大致了解了MySQL数据库独有的插件式体系结构,并了解到存储引擎是MySQL区别于其他数据库的一个最重要特性。存储引擎的好处是,每个存储引擎都有各自的特点,能够根据具体的应用建立不同存储引擎表。对于开发人员来说,存储引擎对其是透明的,但了解各种存储引擎的区别对于开发人员来说也是有好处的。对于DBA来说,他们应该深刻地认识到MySQL数据库的核心在于存储引擎。
由于MySQL数据库的开源特性,用户可以根据MySQL预定义的存储引擎接口编写自己的存储引擎。若用户对某一种存储引擎的性能或功能不满意,可以通过修改源码来得到想要的特性,这就是开源带给我们的方便与力量。比如,eBay的工程师Igor Chernyshev对MySQL Memory存储引擎的改进(http://code.google.com/p/mysql-heap-dynamic-rows/
)并应用于eBay的Personalization Platform,类似的修改还有Google和Facebook等公司。笔者曾尝试过对InnoDB存储引擎的缓冲池进行扩展,为其添加了基于SSD的辅助缓冲池,通过利用SSD的高随机读取性能来进一步提高数据库本身的性能。当然,MySQL数据库自身提供的存储引擎已经足够满足绝大多数应用的需求。如果用户有兴趣,完全可以开发自己的存储引擎,满足自己特定的需求。MySQL官方手册的第16章给出了编写自定义存储引擎的过程,不过这已超出了本书所涵盖的范围。
由于MySQL数据库开源特性,存储引擎可以分为MySQL官方存储引擎和第三方存储引擎。有些第三方存储引擎很强大,如大名鼎鼎的InnoDB存储引擎(最早是第三方存储引擎,后被Oracle收购),其应用就极其广泛,甚至是MySQL数据库OLTP(Online Transaction Processing在线事务处理)应用中使用最广泛的存储引擎。还是那句话,用户应该根据具体的应用选择适合的存储引擎,以下是对一些存储引擎的简单介绍,以便于读者选择存储引擎时参考。
1.3.1 InnoDB存储引擎
InnoDB存储引擎支持事务,其设计目标主要面向在线事务处理(OLTP)的应用。其特点是行锁设计、支持外键,并支持类似于Oracle的非锁定读,即默认读取操作不会产生锁。从MySQL数据库5.5.8版本开始,InnoDB存储引擎是默认的存储引擎。
InnoDB存储引擎将数据放在一个逻辑的表空间中,这个表空间就像黑盒一样由InnoDB存储引擎自身进行管理。从MySQL 4.1(包括4.1)版本开始,它可以将每个InnoDB存储引擎的表单独存放到一个独立的ibd文件中。此外,InnoDB存储引擎支持用裸设备(row disk)用来建立其表空间。
InnoDB通过使用多版本并发控制(MVCC)来获得高并发性,并且实现了SQL标准的4种隔离级别,默认为REPEATABLE级别。同时,使用一种被称为next-key locking的策略来避免幻读(phantom)现象的产生。除此之外,InnoDB储存引擎还提供了插入缓冲(insert buffer)、二次写(double write)、自适应哈希索引(adaptive hash index)、预读(read ahead)等高性能和高可用的功能。
对于表中数据的存储,InnoDB存储引擎采用了聚集(clustered)的方式,因此每张表的存储都是按主键的顺序进行存放。如果没有显式地在表定义时指定主键,InnoDB存储引擎会为每一行生成一个6字节的ROWID,并以此作为主键。
InnoDB存储引擎是MySQL数据库最为常用的一种引擎,而Facebook、Google、Yahoo!等公司的成功应用已经证明了InnoDB存储引擎具备的高可用性、高性能以及高可扩展性。
1.3.2 MyISAM存储引擎
MyISAM存储引擎不支持事务、表锁设计,支持全文索引,主要面向一些OLAP数据库应用。在MySQL 5.5.8版本之前MyISAM存储引擎是默认的存储引擎(除Windows版本外)。数据库系统与文件系统很大的一个不同之处在于对事务的支持,然而MyISAM存储引擎是不支持事务的。究其根本,这也不是很难理解。试想用户是否在所有的应用中都需要事务呢?在数据仓库中,如果没有ETL这些操作,只是简单的报表查询是否还需要事务的支持呢?此外,MyISAM存储引擎的另一个与众不同的地方是它的缓冲池只缓存(cache)索引文件,而不缓冲数据文件,这点和大多数的数据库都非常不同。
MyISAM存储引擎表由MYD和MYI组成,MYD用来存放数据文件,MYI用来存放索引文件。可以通过使用myisampack工具来进一步压缩数据文件,因为myisampack工具使用赫夫曼(Huffman)编码静态算法来压缩数据,因此使用myisampack工具压缩后的表是只读的,当然用户也可以通过myisampack来解压数据文件。
在MySQL 5.0版本之前,MyISAM默认支持的表大小为4GB,如果需要支持大于4GB的MyISAM表时,则需要制定MAX_ROWS和AVG_ROW_LENGTH属性。从MySQL 5.0版本开始,MyISAM默认支持256TB的单表数据,这足够满足一般应用需求。
注意 对于MyISAM存储引擎表,MySQL数据库只缓存其索引文件,数据文件的缓存交由操作系统本身来完成,这与其他使用LRU算法缓存数据的大部分数据库大不相同。此外,在MySQL 5.1.23版本之前,无论是在32位还是64位操作系统环境下,缓存索引的缓冲区最大只能设置为4GB。在之后的版本中,64位系统可以支持大于4GB的索引缓冲区。
1.3.3 NDB存储引擎
2003年,MySQL AB公司从Sony Ericsson公司收购了NDB集群引擎(见图1-1)。NDB存储引擎是一个集群存储引擎,类似于Oracle的RAC集群,不过与Oracle RAC share everything架构不同的是,其结构是share nothing的集群架构,因此能提供更高的可用性。NDB的特点是数据全部放在内存中(从MySQL 5.1版本开始,可以将非索引数据放在磁盘上),因此主键查找(primary key lookups)的速度极快,并且通过添加NDB数据存储节点(Data Node)可以线性地提高数据库性能,是高可用、高性能的集群系统。
关于NDB存储引擎,有一个问题值得注意,那就是NDB存储引擎的连接操作(JOIN)是在MySQL数据库层完成的,而不是在存储引擎层完成的。这意味着,复杂的连接操作需要巨大的网络开销,因此查询速度很慢。如果解决了这个问题,NDB存储引擎的市场应该是非常巨大的。
注意 MySQL NDB Cluster存储引擎有社区版本和企业版本两种,并且NDB Cluster已作为Carrier Grade Edition单独下载版本而存在,可以通过http://dev.mysql.com/downloads/cluster/index.html
获得最新版本的NDB Cluster存储引擎。
1.3.4 Memory存储引擎
Memory存储引擎(之前称HEAP存储引擎)将表中的数据存放在内存中,如果数据库重启或发生崩溃,表中的数据都将消失。它非常适合用于存储临时数据的临时表,以及数据仓库中的纬度表。Memory存储引擎默认使用哈希索引,而不是我们熟悉的B+树索引。
虽然Memory存储引擎速度非常快,但在使用上还是有一定的限制。比如,只支持表锁,并发性能较差,并且不支持TEXT和BLOB列类型。最重要的是,存储变长字段(varchar)时是按照定常字段(char)的方式进行的,因此会浪费内存(这个问题之前已经提到,eBay的工程师Igor Chernyshev已经给出了patch解决方案)。
此外有一点容易被忽视,MySQL数据库使用Memory存储引擎作为临时表来存放查询的中间结果集(intermediate result)。如果中间结果集大于Memory存储引擎表的容量设置,又或者中间结果含有TEXT或BLOB列类型字段,则MySQL数据库会把其转换到MyISAM存储引擎表而存放到磁盘中。之前提到MyISAM不缓存数据文件,因此这时产生的临时表的性能对于查询会有损失。
1.3.5 Archive存储引擎
Archive存储引擎只支持INSERT和SELECT操作,从MySQL 5.1开始支持索引。Archive存储引擎使用zlib算法将数据行(row)进行压缩后存储,压缩比一般可达1∶10。正如其名字所示,Archive存储引擎非常适合存储归档数据,如日志信息。Archive存储引擎使用行锁来实现高并发的插入操作,但是其本身并不是事务安全的存储引擎,其设计目标主要是提供高速的插入和压缩功能。
1.3.6 Federated存储引擎
Federated存储引擎表并不存放数据,它只是指向一台远程MySQL数据库服务器上的表。这非常类似于SQL Server的链接服务器和Oracle的透明网关,不同的是,当前Federated存储引擎只支持MySQL数据库表,不支持异构数据库表。
1.3.7 Maria存储引擎
Maria存储引擎是新开发的引擎,设计目标主要是用来取代原有的MyISAM存储引擎,从而成为MySQL的默认存储引擎。Maria存储引擎的开发者是MySQL的创始人之一的Michael Widenius。因此,它可以看做是MyISAM的后续版本。Maria存储引擎的特点是:支持缓存数据和索引文件,应用了行锁设计,提供了MVCC功能,支持事务和非事务安全的选项,以及更好的BLOB字符类型的处理性能。
1.3.8 其他存储引擎
除了上面提到的7种存储引擎外,MySQL数据库还有很多其他的存储引擎,包括Merge、CSV、Sphinx和Infobright,它们都有各自使用的场合,这里不再一一介绍。在了解MySQL数据库拥有这么多存储引擎后,现在我可以回答1.2节中提到的问题了。
?为什么MySQL数据库不支持全文索引?不!MySQL支持,MyISAM、InnoDB(1.2版本)和Sphinx存储引擎都支持全文索引。
?MySQL数据库速度快是因为不支持事务?错!虽然MySQL的MyISAM存储引擎不支持事务,但是InnoDB支持。“快”是相对于不同应用来说的,对于ETL这种操作,MyISAM会有其优势,但在OLTP环境中,InnoDB存储引擎的效率更好。
?当表的数据量大于1000万时MySQL的性能会急剧下降吗?不!MySQL是数据库,不是文件,随着数据行数的增加,性能当然会有所下降,但是这些下降不是线性的,如果用户选择了正确的存储引擎,以及正确的配置,再多的数据量MySQL也能承受。如官方手册上提及的,Mytrix和Inc.在InnoDB上存储超过1?TB的数据,还有一些其他网站使用InnoDB存储引擎,处理插入/更新的操作平均800次/秒。