1.5. MySQL存储引擎

1.5. MySQL存储引擎

本节主要针对MySQL的存储引擎做一个大致的介绍。在这一节,我们不会太深入细节,因为我们将在整本书中来讨论存储引擎和它们各自的一些行为。但是本书不会是一个完整的源代码文档,如果你一旦决定使用某种存储引擎的话,你应该去看这个存储引擎对应的MySQL官方文档。MySQL针对每个存储引擎也有各自的论坛,论坛上通常会有一些有趣和有用的链接。

如果你只是想要在一个比较高的层面来比较一下各个存储引擎,你可以直接跳到表1-3。

MySQL在底层的文件系统上将每个数据库(也被称为schema)的数据文件夹存储为单独的子文件。当你创建一个表时,MySQL将这个表的定义存储在一个后缀为frm的文件里,文件名即是表名。因此当你创建一个名为MyTable的表时,MySQL将这个表的定义存储在文件MyTable.frm中。因为MySQL利用底层文件系统来保存数据库名和表定义,因此是否大小写敏感取决于使用的平台。在一个基于Windows的MySQL实例上,表和数据库名是大小写不敏感的;而在类Unix系统上,它们是大小写敏感的。每一种存储引擎对于数据和索引的存储是不一样的,但是关于表的定义却是由服务器层来完成的。

如果想要确定一张指定表的存储引擎是什么,可以使用SHOW TABLE STATUS命令来决定。例如,想要确定mysql数据库中的user表的存储引擎,可以执行如下命令:

image

输出显示这是一个MyISAM表。你可能也注意到了许多许多的信息以及一些统计结果。我们来简单地看一下每一行都代表什么意思:

Name

表的名称

Engine

表的存储引擎。在早些的MySQL版本中,这一列被称为Type而不是Engine。

Row_format

行的格式。对于一个MyISAM表来说,这个项的取值可能为Dynamic,Fixed或者Compressed。动态行(Dynamic)表示它的一行数据的长度是可变的,因为它包含了一个变长的字段类型,比如VARCHAR或者BLOB。固定行(Fixed)有固定的大小,均是由不可变长度的类型组成的,比如CHAR和INTEGER。压缩行(Compressed)只存在于压缩的表中,详细的信息可以查看“压缩的MyISAM表”。

Rows

表中当前的行数。对于非事务型表来说,这个数字总是很准确的,但是对于事务型的表来说,这只是一个估计。

Avg_row_length

平均每一行有多少byte的数据

Data_length

整张表一共包含了多少数据(以byte为单位)

Max_data_length

这个表可以使用的最大数据空间。

Index_length

索引数据所使用的磁盘空间大小

Data_free

对于一个MyISAM表来说,这是指分配给表但是却没有使用的磁盘空间。这个空间包含以前删除的行,并且这些空间可以通过将来的INSERT语句来回收。

Auto_increment

下一个AUTO_INCREMENT值

Create_time

当前表被第一次创建的时间

Update_time

当前表最后一次的修改时间

Check_time

当前表最后一次用CHECK TABLE语句或者myisamchk命令进行检查的时间

Collation

当前表的默认的字符集以及针对字符列的排序。

Checksum

如果这个功能被雇用的话,代表整张表内容的一个实时检验和

Create_options

任何在创建表时指定的其他选项。

Comment

这一列包含了一个的变长的额外信息。对于一个MyISAM表来说,它包含了注释,这个值是在表创建时指定的。如果是InnoDB存储引擎,那么表空间的可使用大小会在这里显示。如果是一个视图,那么本项显示为“VIEW”。

1.5.1. MyISAM存储引擎

作为MySQL的默认存储引擎,MyISAM在性能和可用性之间达到了一个很好的折衷,比如全文索引、压缩、GIS功能等。MyISAM不支持事务和行级别的锁。

1.5.1.1. 存储

MyISAM很典型地将每张表的数据存储在两个文件里:一个数据文件和一个索引文件。这两个文件的后缀分别是MYD和MYI。MyISAM文件的格式是平台无关的,这意味着你可以将数据和索引文件从一个intel服务器上拷贝到一台PowerPC或者Sun SPARC上,而不会出任何问题。

MyISAM表可以包含动态或者静态的行。MySQL根据表定义来决定使用哪一种格式。一个MyISAM表所能包含的数据一般由你的数据库服务器的磁盘空间和操作系统所允许的最大文件大小来决定。

MySQL5.0中创建的具有动态长度的MyISAM表默认可以处理256TB的数据,它使用一个6字节的指针来表示数据记录。早期的MySQL版本默认使用4字节的指针,因此它最大可以存储4GB的数据。所有的MySQL版本都可以处理最大8字节的指针。如果想要改变MyISAM表上的指针大小,可以通过指定MAX_ROWS以及AVG_ROW_LENGTH选项来共同决定:

image

在这个凳子中,我们告诉MySQL来准备存储至少32G的数据。如果想要看看MySQL针对这些设置是如何做的,我们只需要看看表的状态即可:

image

正如我们所看到的那样,MySQL如实记录了创建选项到Create_options。并且它选了一个可以存储91GB数据的指针。你也可以在后面利用ALTER TABLE语句来修改指针大小,但是这将会导致整个表以及所有的索引字段的重写,这个过程可能会比较耗时。

1.5.1.2. MyISAM特性

作为MySQL中使用的最早的存储引擎,MyISAM具有众多优秀特性:

锁和并发

MyISAM锁定整张表而不是行。读者在需要读时可以获取一个共享的读锁。写者在需要时可以得到一个互斥的写锁。但是当一个查询操作正在进行时,你还是可以插入一条记录到表中。这是一个非常重要而且有用的特性。

自动修复

MySQL支持MyISAM表的自动检查和修复。

手动修复

你可利用CHECK TABLE或者REPAIR TABLE语句来检查一个表的错误并且修复它们。你同样可以在服务器离线的情况下利用myisamchk命令行工具来检查和修复表。

检索特性

你可以创建在MyISAM表中为BLOB或者TEXT类型的列的前500个字符创建索引。MyISAM支持全文索引,这种索引会分词,以用来处理一些复杂的查询。如果想要了解更多的关于索引的信息,可以查看第3章。

延迟的索引更新

MyISAM表如果在创建选项里指定为DELAY_KEY_WRITE的话,它不会立即将改变的索引数据写到硬盘,而是将这个改变缓存到内存中。当表被关闭或者缓冲区需要修整时,它会将索引一次性写到硬盘。这个特性可以在修改很频繁的表上极大的提高性能。但是当一个服务器或者操作系统崩溃时,这些索引肯定会被损坏,当然也需要修复。你可通过写一个脚本来在每次重启服务器前先用myisamchk来检查一下,或者你也可以使用自动修复选项。(即使你不使用DELAY_KEY_WRITE,这些安全性保障也是一个很好的习惯。)你既可以对整个数据库设置延迟的索引更新,也可以只针对某些表来进行设置。

1.5.1.3. 压缩的MyISAM表

有一些表,比如基于CD-ROM或者DVD-ROM的应用以及一些嵌入式环境中,它们的数据从创建起就不再改变。这些情景可以很好地利用MyISAM的压缩表。

你可以利用myisampack工具来压缩一个表。你不能对压缩后的表进行修改(当然你可以先解压,再修改,最后再重新压缩表),但是却可以节省硬盘空间。因此它可以带来更高的效率,因为小的硬盘空间代表着少的硬盘寻址。压缩的MyISAM表可以有索引,但是它们是只读的。

解压数据的开销对于运行在现代硬件上的应用来说是微不足道的,相比而言,硬盘的寻址开销要比解压大得多。另外MyISAM对于数据的压缩是以行为单位的,因此MySQL不需要将整个表来解压,而只需要获取单行即可。

1.5.2. MyISAM Merge存储引擎

MyISAM Merge引擎是MyISAM的一个变种。一个Merge表是将一系列的完全相同的MyISAM表合并成为一个虚拟表。这在日志和数据仓库应用中将变得极为有用。具体的内容可以查看“Merge表以及分表”章节。

1.5.3. InnoDB存储引擎

InnoDB是为事务处理而设计的,特别是为处理多而生存周期比较短的事务而设计,一般来说这些事务基本上都会正常结束,只有少数才会回滚。它是目前事务型存储引擎中最为著名的。它的性能和自动故障恢复使得它同时也作为一个优秀的非事务存储引擎被广泛使用。

InnoDB将数据存储在一个或者多个被共同称为表空间的文件中。一个表空间基本上作为一个黑盒子而由InnoDB自己来维护。在MySQL4.1以及之后的版本中,InnoDB都可以将每个表的数据以及索引存储到不同的文件中。InnoDB还可以利用磁盘分区功能来创建它的表空间。更详细的内容可以查看“InnoDB的表空间”一章。

InnoDB利用MVCC来实现高并发性,并且它也实现了SQL的4种标准隔离级别。它的默认隔离级别是“可重复读REPEATABLE READ”,同时它还利用一种“next-key锁定”策略来防止这个级别的幻读;另外InnoDB并不是只锁定你在一个语句中使用到的记录,它同时会锁定索引结构的缺口,以防止幻写。

InnoDB表是基于一种被称为“簇索引”之上的,关于“簇索引”的内容我们将会在第3章进行详细的介绍。InnoDB的索引结构与其他的MySQL存储引擎很不相同。事实上,它能够提供基于主键的非常快速的查询。但是由于二级索引(非主键的索引)都会包含主键列,因此如果你的主键如果很大的话,将会导致你的索引整个会变得很大。如果你的表上有许多的索引的话,你应该尽可能的使用一个小的主键。InnoDB不会压缩它的索引。

在这本书正在写作的时候,InnoDB还不能依赖于排序来构造索引,这一点MyISAM是支持的。因此InnoDB加载数据和创建索引相对于MyISAM来说会慢一些。任何会改变InnoDB表结构的操作都会引起整个表的重建,包括所有的索引。

InnoDB在设计的时候,多数的服务器还是基于慢硬盘,单CPU以及受限的内存数量的。而在具有大量内存和快速硬盘的多核服务器已经越来越便宜的今天,InnoDB就有很多的扩展性问题。InnoDB的开发者们正在着手解决这些问题,但是在本书出版之前,其中的一些还是没有得到很好的解决。

除了它的高并发性之外,InnoDB的下一个著名的特性是外键约束,这一点MySQL服务器本身并不支持。InnoDB提供了基于主键的极快速的查询。

InnoDB有许多的内部优化。这包括预见性地从硬盘上将数据事先读到内存,自适应的在内存中进行哈希索引构建以期得到快速查询,以及用来提高插入速度的插入记录缓冲。我们将会在本书的后面详细地对这部分内容进行说明。

InnoDB的行为是非常错综复杂的,如果您正在使用InnoDB的话,我们高度推荐阅读MySQL手册中的“InnoDB事务模型和锁”章节。在利用InnoDB来构建一个应用之前,有许多的“惊喜”和“期望”你应该事先都知道。

1.5.4. Memory存储

内存表(以前被称为HEAP表)当你需要极快速的获取一些不需要修改或不需要在重启后持久化的数据时会非常有用。内存表一般会比MyISAM表快上一个数量级。所有的数据都被存储在内存中,因此查询不需要磁盘IO等待。内存表的表结构在会服务器重启过程中进行持久化,但是数据不会。

下面是一些内存表比较好的应用:

l 作为查询表或者映射表,如邮编和省份的映射表

l 作为周期性更新的数据缓存表

l 作为分析数据的中间结构表

内存表支持HASH索引,HASH索引在查询中非常快速。关于“哈希索引”的具体内容可以查看后面章节。

尽管内存数据库很快,但是它们仍然不用作为一个基于硬盘表的替换产品。因为它只支持表级别的锁定,这使得它的写并发效率很快,另外它不支持TEXT和BLOB类型。另外,内存数据库只支持固定大小的行,因此它会将VARCHAR作为CHAR来进行存储,这将会浪费许多内存。

MySQL将内存引擎作为处理查询时的中间结果的内部临时数据库来使用。如果中间结果太大或者有TEXT和BLOB列的话,MySQL会把内存表转换为MyISAM表。我们将在后面章节中详细讨论这个问题。

人们经常把内存表和临时表相混淆。事实上临时表是用CREATE TEMPORARY TABLE命令来他创建的。一个临时表可以使用任何存储引擎;它与使用内存引擎的表不是一回事。临时表仅对于单个的连接是可见的,当连接关闭时这个临时表就会被销毁。

1.5.5. Archive存储引擎

Archive引擎只支持INSERT和SELECT语句,并且它不支持索引。它比MyISAM使用更少的磁盘IO,因此它会在写操作之前将数据缓存并利用zlib来压缩。而SELECT查询操作则需要一个全表扫描。因此Archive表是日志和数据采集的理想选择,在这些应用中,一般分析是需要扫描整张表或者需要在一个备份主机上进行快速的INSERT操作。备份从机上可以为相同的表选用一个不同的存储引擎,这意味着从机上的表可以有索引,以达到快速分析的目的。

Archive引擎支持行级别的锁以及一个特殊的缓冲系统以期达到高并发的写操作。它在查询时会将整个表扫描一次。它同时也会将批量写操作屏蔽直到全部的写操作完成。这些特性模拟了事务和MVCC行为的一些方面,但是Archive引擎并不是一个事务型引擎。它只是一个优化了插入操作以及压缩了数据的引擎。

1.5.6. CSV存储引擎

CSV引擎可以将以逗号分隔的CSV文件当作数据表来处理,但是它不支持索引。这个引擎允许你在服务器运行的时候将数据文件拷贝进数据库或者从数据库里拷贝出去。如果你从一个表单中导出了CSV文件并且将它保存到MySQL服务器的数据目的,服务器可以立即读取到它。与此相似的,如果你将数据写入到一个CSV表中,一个外部程序也可以立即读到它。CSV表作为数据格式转换以及特定的日志极为有用。

1.5.7. Federated存储引擎

Federated引擎并不在本地存储数据。每个Federated表都引用一个远程的MySQL上的表,因此它实际将所有的操作转交给远程MySQL来完成。它有时会被用来完成一些类似于hack的工作,比如用来进行复制。

这个引擎目前有许多很怪异的地方,同时也有很多的限制。因为Federated引擎的工作方式,我们可以想像,如果是需要根据主键来获取一条记录或者将一个记录插入到一个远程服务器上,这时Federated引擎将会很有用。它对于聚合查询、连接以及其他的一些基本操作效果并不是很好。

1.5.8. Blackhole存储引擎

黑洞引擎并没有存储机制。它会丢弃所有的INSERT操作。但是,服务器将执行语句写给Blackhole引擎时它仍然会记录日志,因此它们可以被复制到从机或者只是简单地作为日志备份。这使得黑洞引擎作为虚复制以及日志审计的首选引擎。

1.5.9. NDB Cluster存储引擎

MySQL AB 2003年从索尼爱立信拿到了NDB Cluster引擎。这个引擎最初是为高速(实时性能需求)、冗余以及负载均衡需求而设计的。尽管它将数据写到了硬盘,但是它内存中仍然存在着所有的数据,并且这些数据针对主键查询进行了优化。MySQL之后添加了一些其他的索引方法以及许多优化,MySQL5.1之后允许一些列被存储在硬盘上。

NDB架构比较独特:一个NDB簇与其他的类似概念完全不同,比如Oracle簇。NDB是基于完全不共享的概念来构建的。与其他类型的簇依赖于存储点网络或者大的中心存储方案不一样,NDB没有这些东西。一个NDB数据库由数据结点组成,并管理这些结点以及SQL结点(即MySQL实例)。每一个数据结点持有整个簇数据中的一片数据。这些片断数据是有冗余的,因此系统中可能会在不同的节点中存储同一份数据的多个拷贝。通常每个节点会对应一台物理服务器以致力于提供冗余和高可靠性。从这个意义上来说,NDB更像是RAID在服务器级别上的实现。

管理节点被用于获取中央控制信息、监视和控制其他的簇结点等。所有的数据结点之间可以互相通信,并且所有 的MySQL服务器与所有 的数据结点之间是互联的。比较低的网络延时对于NDB簇来说极为重要。

提醒一下:NDB簇是一个非常酷的技术,当然也值得花气力去研究来满足你的好奇心,但是许多技术人士倾向于找到各自理由来使用它来完成一些它并不适合完成的工作。以我们的经验来看,即使在认真地研究过它的使用之后,许多人还是不知道这个引擎是干什么的以及它是如何工作的,这往往需要用户在实际安装了它并且使用了一段时间之后。这样导致的后果往往就是时间上的浪费,因为它并不是一个通用的存储引擎。

一个很令人惊奇的事实是,NDB目前执行JOIN操作是在MySQL服务器级而不是在存储引擎级别来完成。因为所有的NDB数据必须从网络上来获取,复杂的JOIN将会表现的非常慢。另一方面来说,单表查询会非常地快,因为多个数据节点可以提供整体结果的一个部分。这只是你在一个特定的NDB应用中应该考虑的许多方面中的一个而已。

NDB是如此庞大而复杂以致于我们将不会在本书中再对它进行更进一步的讨论。如果你对NDB感兴趣的话,你应该去找一本致力于这个话题的书来学习一下。我们只能说,它并不是你想像中那样的东西,而且它对于大多数的传统应用来说也不适合。

1.5.10. Falcon存储引擎

Falcon存储引擎的发明者是Jim Starkey,一个数据库先驱者,他在早期的发明包括Interbase,MVCC以及BLOB列类型等。MySQL AB在2006年从Jim那里获得了Falcon技术,并且Jim目前也工作于MySQL AB。

Falcon是为今天的硬件而设计的,特别是为那些拥有多个64位处理器以及大量内存的服务器而设计,但是它同时也可以运行于一些更通用的环境中。Falcon使用了MVCC同时试图将事务整个运行于内存中。这使得回滚和恢复操作变得非常地快。

Falcon在本书写作的时候还未完成(比如,它还不能将它的提交操作与binlog相同步),因此我们不会对它作过多的描述。甚至我们关于它做的一些早期的性能测试也将会在它真正发布过时。它似乎对许多线上服务很有吸引力,但是我们目前能知道的东西还不是很多。

1.5.11. SolidDB存储引擎

solidDB存储引擎是由Solid Information Technology(http://www.soliddb.com)开发的,这是一款利用MVCC来实现的事务型存储引擎。它既同时支持悲观和乐观并发控制,这一点其他的存储引擎目前都不支持。solibDB的MySQL版本包括对外键的完全支持。它在许多方面与InnoDB很相似,比如它使用了簇索引。solidDB还包括一个没有额外开销的在线备份功能。

solidDB产品是一个完整的打包程序,包括solidDB存储引擎、MyISAM存储引擎以及MySQL服务器。solidDB与MySQL之间的结合出现于2006年的晚些时候。但是底层的技术以及代码却是经过了该公司15年的完善。Solid公司保证和支持了整个产品。它是基于GPL协议的,并且提供了一个类似于MySQL服务器形式的商业版本。

1.5.12. PBXT存储引擎

PBXT引擎由Paul McCullagh开发,它是一款事务型存储引擎,并且它的设计是很独特的。它的一个很与众不同的特征就是如何来使用事务日志和数据文件来防止“write-ahead”日志,这可以极大的减少事务提交的开销。这个架构给了PBXT很大的提高写并发的空间,并且测试也表明它在某些特定的操作下比InnoDB要快。PBXT也使用了MVCC并且支持外键约束,但是它不使用簇索引。

PBXT是一个比较新的引擎,所以它必须在未来的产品环境中来证明它自己的价值。例如,它对于持久性事务的实现只是在我们写这本书的时候才完成。

1.5.13. Maria存储引擎

Maria是一个由MySQL的一些顶级工程师开发的新型存储引擎,包括Michael Widenius,他创建了MySQL。最初的1.0版本只是包括了一些关于这个引擎的计划。

这个存储引擎的目的是用来替换MyISAM。MyISAM是MySQL的默认存储引擎,并且它也被用于一些内部任务,比如一些权限表以及运行时产生的临时表等。下面是关于这个引擎的一些亮点:

1、可以针对表来选择是采用事务还是非事务

2、故障恢复,即使一个表正在运行于非事务模式

3、行锁定以及MVCC

4、更好的BLOB处理

1.5.14. 其他存储引擎

许多的第三方也提供了其他一些存储引擎,并且有许多特定目的和实验性的存储引擎(比如一个专门用于查询web service的存储引擎)。这些引擎中的一些是非正式开发的,可能只是有一两个工程师来完成的。这是因为MySQL中创建存储引擎是相对容易的。另外,许多这种引擎都没有公开,一方面是因为它们的功能比较有限。用户如果需要的话,可以自行去研究这些引擎。

1.5.15. 选择正确的存储引擎

当设计基于MySQL的应用时,你应该首先决定利用哪种存储引擎来存储你的数据。如果你不在设计阶段考虑这个问题,你极有可能在后面的开发中面临复杂的情况 。你很可能发现默认的存储引擎并没有提供你需要的一个特性,比如事务,或者你需要比MyISAM的表锁定更细粒度的读写锁定。

因为你可以在表级别来选择存储引擎,因此你需要对如何使用每个表以及每个表中存的数据有一个清楚的认识。它不仅可以帮助你对于整个应用有一个比较好的整体理解,同时也可以对它的增长规模有一个估计。借助于这些信息,你可开始决定利用哪些存储引擎来完成这些任务了。

注:对于不同的表使用不同的存储引擎并不是很必要。如果你可以为所有的表使用同一个存储引擎来完成既定的任务,那么你将会发现你后面的工作要简单很多。

1.5.16. 存储引擎选择的考查点

尽管许多因素都可以对存储引擎的选择造成影响,它通常还是可以归结为一些很基本的考查点。下面列出就是一些主要的考查点:

事务

如果你的需要事务,那么InnoDB是最稳定、并且集成度比较好的经过验证的选择。但是随着时间的推进,我们也将会看到许多更有竞争力的事务型引擎出现。如果不需要事务,而只是执行一些基本的查询和插入操作的话,MyISAM是一个比较好的选择。有时一个应用的一些特定的组件(比如日志)可能会归入这类应用。

并发

开发性需求的最好的衡量标准是你的工作量。如果你只量需要插入和写操作的并发性的话,不管你相信不相信,MyISAM是一个很不错的选择。如果你需要许多操作混合执行而互不影响的话,一个支持行锁的引擎将会是比较不错的选择。

备份

对于常规备份的需求也可能成为影响你的表选择的一个因素。如果你的服务器可以定时的关闭来备份的话,所有的存储引擎在处理上基本都差不多。但是如果你需要执行一个线上备份的话,选择就不是那么清晰了。第11章将会针对这个话题进行更详细的描述。但是需要记住一点,如果选用了多种存储引擎的话,将会增大备份和服务器调优的复杂性。

故障恢复

如果你有很多的数据,你需要很严肃地考虑它需要多久从一个故障中恢复。MyISAM表相对于InnoDB表来说,一般更容易损坏,并且需要花更多的时间来恢复。事实上这是为什么很多在即使不需要事务的时候也仍然选择InnoDB的原因。

特殊功能

最后,你有时可能会发现一个应用依赖于一些特定的功能或者优化,而这些优化可能只有一些MySQL的存储引擎提供。比如,许多应用依赖于簇索引的优化。在这个时候,你的选择就只有InnoDB和solidDB了。另一方面来说,只有MyISAM支持全文检索。如果一个存储引擎只符合其中的一些条件,而不符合其他的,你就需要妥协或者找到一个更聪明的设计方案了。你可能会经常遇到一种存储引擎只符合你的众多需求中的一些的情况 。

你并不需要读到这里的时候就决定使用哪种存储引擎。本书的其余部分还有许多针对每种存储引擎的优缺点的内容,以及许多架构和设计方面的经验。通俗地说,一个问题很可能有许多你想不到的选择,并且当你阅读了更多的东西之后再回头来看这个问题,可能会更有帮助。

1.5.17. 实际的例子

如果离开了现实世界的上下文的话,上面的这些考查点可能会让人感觉到很抽象,因此让我们来看一些通用的数据库应用。我们将会看到许多的表,并且来决定哪张表最适合使用哪种存储引擎。在下一节我们将会给出一个总结。

1.5.17.1. 日志

假如你想要用MysQL来实时记录从呼叫中心的电话来的每一个电话的日志记录。或者你可能已经为Apache安装了mod_log_sql模块,这样你就可以将网站所有的访问记录到数据库中。在这样的一个应用中,速度可能是最重要的目标,你不想要数据库成为瓶颈。MyISAM和Archive存储引擎将会是很好的选择,因为它们只有很低的开销并且可以一秒钟插入成千上万条记录。PBXT存储引擎也可能特别适合这个目的。

然而,如果你决定对已经记录的数据进行分析总结,那么事情就开始变得有趣了。根据你所使用的查询的不同,有很大的可能性因为数据采集的影响而使得整个插入过程变慢。这个时候你应该怎么办?

一个解决方案是利用MySQL的内置复制特性来将数据克隆到第二台服务器(从机)上,然后在从机上运行对于对于时间和CPU要求比较高的查询。这使得主机只是插入操作,并且可以使你在从机上运行任何你需要的查询而不必担心对日志实时性的影响。

你也可以将查询分成开销很小的查询来完成任务,但是不要指望这个策略能一直有效,因为你的程序的规模一直在增长。

另外的一个选择是使用Merge表。Merge表不会总是将日志记录到同一个表,可以通过调整应用使得日志按照需求记录到按年、月、日分表的表中去,比如web_log_2009_01或者web_log_2009_01_01。然后定义一个Merge表,它包含了你想要进行综合分析的数据。如果你需要分析一天或者一周的数据,那么这个策略可以直接使用,而你只需要创建分得更细的表,比如web_logs_2008_01_01。你的应用将日志插入到一张表中,而你而在其他的表上进行查询。

1.5.17.2. 只读或者很少写的表

包含用于创建目录或者列出某类数据(如职业、标售、财产等)的表通常读要远大于写操作的次数。这使得它们成为MyISAM表的首要客户,当然前提是你不在乎当MyISAM崩溃之后的故障恢复的话。不要低估这个问题,很多用户其实对于一个不认真尝试将数据写入硬盘的存储引擎所带来的风险并不是很清楚。

注:一个很好的想法是在一台测试服务器上运行一个实际负载的模拟,然后去拨掉电源插销。从故障中恢复数据的第一手经验是无价。它可以能够轻松应对后面遇到的许多很令人头痛的问题。

不要只是单纯的相信“MyISAM比InnoDB快”的经验。它并不是无条件的正确的。我们可以举出很多InnoDB远比MyISAM快的例子,尤其是对于那些使用簇索引或者数据正好在内存中的应用来说。当你读过本书的其他部分之后,你就会对于影响存储引擎性能的因素有一个比较清楚的认识(数据量、IO率、主键vs次主键等等),这样子你才能够对哪些因素对于你的应用有影响有清楚的理解。

1.5.17.3. 订单处理

当你处理不管何种类型的订单处理时,事务都是不可或缺的。半完成状态的订单不可能使你的客户喜欢你所提供的服务。另外一个很重要的因素是存储引擎是否支持外键约束。在这本书完成之时,InnoDB似乎还是你最好的选择,但是其他的事务型存储引擎也可以作为一个候选者。

1.5.17.4. 股票报价

如果你正在为个人分析而收集股票报价的话,一般来说,MyISAM将会工作地很好。但是,如果你正在运行一个流量很大的web service,它有实时的报价反馈并且有成千上万的用户的话,查询不能有等待。许多客户可能同时都想往同一张表里插入数据或者读取数据,因此行级别的锁或者一种可以减少更新的策略都是可选择的解决方案。

1.5.17.5. BBS的论坛

针对主题的讨论对于MySQL的用户来说是一个很有趣的问题。有许多免费的基于PHP和Perl的系统都可以提供针对主题的讨论。其中许多应用并没有考虑数据库效率问题,因此它们一般都会对一个请求查询多次数据库。有一些应用是不针对具体数据库的,因此它们并没有使用任何数据库的特性来提升性能。它们会针对多个主题来更新计数器,收集使用统计等。有些应用甚至采用单表来存储它们所有的数据。事实上造成的结果是,少部分中心表成为读写操作的重心,而用来保证一致性的锁成为造成竞争的基本来源。

如果不考虑设计上的缺陷的话,这些系统多数都是为了中小型负载而设计的。然而,如果一个网站增长得很大,并且流量也很可观时,它很可能就会变得很慢了。一个显而易见的解决方案是换用另外一种可以处理大量读写操作的存储引擎,但是试图这么做的用户往往会惊讶地发现他们的系统甚至比没有转换之前更慢。

这些用户并没有意识到系统可能正在使用一个特定的查询,一般是如下这样子的查询:

image

问题是,并不是所有的存储引擎对这个查询都会运行地很快:MyISAM可以,但是其他存储引擎不会。还有许多其他的例子也是针对每种存储引擎会有不同的表现。第二章将会教会你如何处理这些意想不到的情况,找到并修复这些问题。

1.5.17.6. CD-ROM应用

如果你需要分发一个使用MySQL数据文件的基于CD-ROM或者DVD-ROM的应用的话,可以考虑使用MyISAM或者压缩的MyISAM表,它们可以很容易地隔离出来并拷贝到其他媒介上去。压缩的MyISAM表比未压缩的表使用更少的空间,但是它是只读的。这对于某些特定应用来说可能会造成问题,但是因为数据本身就存储在只读媒介上,那就没有什么理由来不使用压缩的MyISAM表了。

1.5.18. 存储引擎总结

表1-3总结了MySQL众多流行存储引擎的事务以及锁相关的特征。MySQL版本栏展示了你使用该引擎所需要的最低MySQL版本,其中一些存储引擎和服务器版本可能需要用户自己来编译。在列中的“ALL”说明包括了从MySQL3.23之后的所有版本。

图表 1‑3 MySQL存储引擎总结

image

1.5.19. 表的存储引擎转换

将一个表从一种存储引擎转换成另外一种有许多种方法,每一种都有它各自的优缺点。在下面的章节中我们将来详细介绍三种更大众的方法。

1.5.19.1. 修改表

最简单的办法莫过于直接使用ALTER TABLE命令。下面的命令可以将mytable表转换为Falcon:

image

这个语法对于所有的存储引擎都是有效的,但是这里有一个陷阱:它可能会需要很长的时间。MySQL将会执行一个行到行的拷贝,将旧表的数据拷贝到新表中去。这个段时间里,你可能会将整个服务器的磁盘IO用尽,并且在这个过程中旧表是处于锁定状态的。因此,如果你需要在一个使用率很高的表上进行这个操作需要额外的小心。当然,你也可以使用下面讨论的其他方法中的一个,它们都会先拷贝一份原表。

当你将一个表的存储引擎从一种转换成另外一种时,任何针对原存储引擎的特性都会被丢弃。举个例子来说,如果你把一个InnoDB表转换成MyISAM,然后再转换回来,那么你将会发现InnoDB表上定义的所有外键约束都没有了。

1.5.19.2. 导出和导入

为了在整个转换过程中得到更大的控制权,你可以选择利用mysqldump工具先将表里的数据导出为文本文件。当你将表导出之后,你可简单地修改一下导出文件使得CREATE TABLE语句中的存储引擎变成你需要的。注意一定要将表名也修改了,因为同一个数据库里不可能有同名的表,即使它们是不同的类型。另外mysqldump默认会导出一个DROP TABLE命令,因此如果你不小心的话,你可能就会丢失数据。

你可以在第11章找到更多关于如何将数据有效地导出和加载的建议。

1.5.19.3. CREATE和SELECT

第三种方法是在前两种之间的一个融合,同时具有第一种的速度和第二种的安全性。与第二种导出整个表并且将它整个转换不同,第三种方案采用先建一张表,然后利用MySQL的INSERT…SELECT语法来填充它,如下所示:

image

如果你的数据不是很多的话,这个方案将会工作地很好;但是如果你有很多数据的话,比较有效的方法是增量式填充,将整个转换分成多个事务块来执行,这样子可以避免重做日志变得很大。假如id是主键,可以利用反复执行下面的命令来将表中的数据拷贝到新表中去(每次都增大x和y):

在这个过程完成之后,你将有拥有两张表,一个是原表,你可以在不再需要它时将它drop掉;另外一个是新表,它现在已经被完全的填充。如果需要防止数据的不一致拷贝将记得将原表锁定。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值