注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

God is U 做自己的上帝

富原孤島--只发优质级的文章

 
 
 

日志

 
 

MySQL存储引擎之MyISAM  

2009-06-26 11:05:09|  分类: [数据库裤] |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

MyISAM是默认存储引擎。它基于更老的ISAM代码,但有很多有用的扩展。(注意MySQL 5.1不支持ISAM)。

每个MyISAM在磁盘上存储成三个文件。第一个文件的名字以表的名字开始,扩展名指出文件类型。

.frm文件存储表定义。
数据文件的扩展名为.MYD (MYData)
索引文件的扩展名是.MYI (MYIndex)

要明确表示你想要用一个MyISAM表格,请用ENGINE表选项指出来:

CREATE TABLE t (i INT) ENGINE = MYISAM;

注释:老版本的MySQL使用TYPE而不是ENGINE(例如,TYPE = MYISAM)。MySQL 5.1为向下兼容而支持这个语法,但TYPE现在被轻视,而ENGINE是首先的用法。

一般地,ENGINE选项是不必要的;除非默认已经被改变了,MyISAM是默认存储引擎。

你可以用myisamchk工具来检查或修复MyISAM表。你也可以用myisampack来压缩MyISAM表,让它们占更少的空间。

如下是MyISAM存储引擎的一些特征:

·       所有数据值先存储低字节。这使得数据机和操作系统分离。二进制轻便性的唯一要求是机器使用补码(如最近20年的机器有的一样)和IEEE浮点格式(在主流机器中也完全是主导的)。唯一不支持二进制兼容性的机器是嵌入式系统。这些系统有时使用特殊的处理器。

先存储数据低字节并不严重地影响速度;数据行中的字节一般是未联合的,从一个方向读未联合的字节并不比从反向读更占用更多的资源。服务器上的获取列值的代码与其它代码相比并不显得时间紧。

·        大文件(达63位文件长度)在支持大文件的文件系统和操作系统上被支持。

·         当把删除和更新及插入混合的时候,动态尺寸的行更少碎片。这要通过合并相邻被删除的块,以及若下一个块被删除,就扩展到下一块来自动完成。

·         每个MyISAM表最大索引数是64。 这可以通过重新编译来改变。每个索引最大的列数是16个。

·         最大的键长度是1000字节。这也可以通过编译来改变。对于键长度超过250字节的情况,一个超过1024字节的的键块被用上。

·         BLOBTEXT列可以被索引。

·         NULL值被允许在索引的列中。这个占每个键的0-1个字节。

·         所有数字键值以高字节为先被存储以允许一个更高地索引压缩

·        当记录以排好序的顺序插入(就像你使用一个AUTO_INCREMENT列之时),索引树被劈开以便高节点仅包含一个键。这改善了索引树的空间利用率。

·         每表一个AUTO_INCREMEN列的内部处理。MyISAMINSERTUPDATE操作自动更新这一列。这使得AUTO_INCREMENT列更快(至少10%)。在序列顶的值被删除之后就不能再利用。(当AUTO_INCREMENT列被定义为多列索引的最后一列,可以出现重使用从序列顶部删除的值的情况)。AUTO_INCREMENT值可用ALTER TABLEmyisamch来重置。

·         如果数据文件中间的表没有自由块了,在其它线程从表读的同时,你可以INSERT新行到表中。(这被认识为并发操作)。自由块的出现是作为删除行的结果,或者是用比当前内容多的数据对动态长度行更新的结果。当所有自由块被用完(填满),未来的插入又变成并发。

·         你可以把数据文件和索引文件放在不同目录,用DATA DIRECTORYINDEX DIRECTORY选项CREATE TABLE以获得更高的速度,请参阅13.1.5节,“CREATE TABLE语法”

·         每个字符列可以又不同的字符集,

·         MyISAM索引文件里又一个标志,它表明表是否被正确关闭。如果用--myisam-recover选项启动mysqldMyISAM表在打开得时候被自动检查,如果被表被不恰当地关闭,就修复表。

·         如果你用--update-state选项运行myisamchk,它标注表为已检查。myisamchk --fast只检查那些没有这个标志的表。

·         myisamchk --analyze为部分键存储统计信息,也为整个键存储统计信息。

·         myisampack可以打包BLOBVARCHAR列。

MyISAM也支持下列特征:

·         支持true VARCHAR类型;VARCHAR列以存储在2个字节中的长度来开始。

·         VARCHAR的表可以有固定或动态记录长度。

·         VARCHARCHAR列可以多达64KB

·         一个被搞乱的已计算索引对可对UNIQUE来使用。这允许你在表内任何列的合并上有UNIQUE。(尽管如此,你不能在一个UNIQUE已计算索引上搜索)。

MyISAM存储引擎,有一个更详细的论坛在http://forums.mysql.com/list.php?21

15.1.1MyISAM启动选项

下列对mysqld 的选项可用来改变MyISAM表的行为:

·         --myisam-recover=mode

设置为崩溃MyISAM表自动恢复的模式。

·         --delay-key-write=ALL

对任何MyISAM表的写操作之间不要刷新键缓冲区。

注释:如果你要这么做。当表在使用中之时,你应该不使用来自另一个程序的MyISAM表(比如从另一个MySQL服务器或用myisamchk)。这么做会导致索引被破坏。

对使用--delay-key-write的表,使用--external-locking没有帮助。

下列系统变量影响MyISAM表的行为:

·         bulk_insert_buffer_size

用在块插入优化中的树缓冲区的大小。注释:这是一个per thread的限制。

·         (OBSOLETE) myisam_max_extra_sort_file_size

这个参数已经不在MySQL中使用。

·         myisam_max_sort_file_size

如果临时文件会变得超过索引,不要使用快速排序索引方法来创建一个索引。注释:这个参数以字节的形式给出。

·         myisam_sort_buffer_size

设置恢复表之时使用的缓冲区的尺寸。

如果用--myisam-recover选项启动mysqld,自动恢复被激活。在这种情况下,当服务器打开一个MyISAM表之时,服务器会检查是否表被标注为崩溃,或者表的打开计数变量是否不为0且你正用--skip-external-locking运行服务器。如果这些条件的任何一个为真,下列情况发生:

·         表被查错。

·         如果服务器发现一个错误,它试着做快速表修复(排序且不重新创建数据文件)。

·         如果修复因为数据文件中的一个错误而失败(例如,一个重复键错误),服务器会再次尝试修复,这一次重建数据文件。

·         如果修复仍然失败,服务器用旧修复选项方法再重试一次修复(一行接一行地写,不排序)。这个方法应该能修复任何类型的错误,并且需要很低的磁盘空间。

如果恢复不能够从先前完成的语句里恢复所有行,而且你不能在--myisam-recover选项值指定FORCE,自动修复会终止,并在错误日志里写一条错误信息:

Error: Couldn't repair table: test.g00pages

如果你指定FORCE,取而代之地,类似这样的一个警告被给出:

Warning: Found 344 of 354 rows when repairing ./test/g00pages

注释:如果自动恢复值包括BACKUP,恢复进程创建文件并用tbl_name-datetime.BAK形式取名。你应该有一个cron脚本,它自动把这些文件从数据库目录移到备份媒质上。

15.1.2.键所需的空间

MyISAM表使用B型树索引。你可以粗略地计算索引文件的大小为(key_length+4)/0.67, 加上所有的键之和。当所有键以排序的顺序插入并且表没有任何压缩的键之时,以上估计是对最坏的情况的。

字符串索引是被空间压缩的。如果第一个字符串索引部分是字符串,它也被加前缀压缩。如果字符串列有许多拖曳空间,或字符串列是一个总是不用完全长度的VARCHAR列,空间压缩使得索引文件比最坏情况时的数值要小。前缀压缩被用在以字符串开始的键上。如果有许多具有同一前缀的字符串,前缀压缩是有帮助的。

MyISAM表,你也可以在创建表的时候通过指定PACK_KEYS=1来前缀压缩数字。当数字被以高字节优先存储之时,若你有许多具有同一前缀的整数键,上述方法是有帮助的。

 MyISAM表的存储格式

MyISAM支持三种不同存储格式。其中两个(固定格式和动态格式)根据正使用的列的类型来自动选择。第三个,即已压缩格式,只能使用myisampack工具来创建。

当你CREATEALTER一个没有BLOBTEXT列的表,你可以用ROW_FORMAT表选项强制表的格式为FIXEDDYNAMIC。这会导致CHARVARCHAR列因FIXED格式变成CHAR,或因DYNAMIC格式变成VARCHAR

通过用ALTER TABLE指定ROW_FORMAT={COMPRESSED | DEFAULT},你可以压缩或解压缩表。

15.1.3.1. 静态(固定长度)表特征

静态格式是MyISAM表的默认存储格式。当表不包含变量长度列(VARCHAR, BLOB, TEXT)时,使用这个格式。每一行用固定字节数存储。

MyISAM的三种存储格式中,静态格式就最简单也是最安全的(至少对于崩溃而言)。静态格式也是最快的on-disk格式。快速来自于数据文件中的行在磁盘上被找到的容易方式:当按照索引中的行号查找一个行时,用行长度乘以行号。同样,当扫描一个表的时候,很容易用每个磁盘读操作读一定数量的记录。

MySQL服务器正往一个固定格式MyISAM文件写的时候,如果计算机崩溃了,安全是显然的。在这种情况下,myisamchk可以容易地决定每行从哪里开始到哪里结束,所以它通常可以收回所有记录,除了写了一部分的记录。注意,基于数据行,MyISAM表索引可以一直被重新构建。

静态格式表的一般特征:

·         CHAR列对列宽度是空间填补的。

·         非常快。

·         容易缓存。

·         崩溃后容易重建,因为记录位于固定位置。

·         重新组织是不必要的,除非你删除巨量的记录并且希望为操作系统腾出磁盘空间。为此,可使用OPTIMIZE TABLE或者myisamchk -r

·         通常比动态格式表需要更多的磁盘空间。

15.1.3.2. 动态表特征

如果一个MyISAM表包含任何可变长度列(VARCHAR, BLOBTEXTDynamic),或者如果一个表被用ROW_FORMAT=DYNAMIC选项来创建,动态存储格式被使用。

这个格式更为复杂一点,因为每行有一个表明行有多长的头。当一个记录因为更新的结果被变得更长,该记录也可以在超过一个位置处结束。

你可以使用OPTIMIZE TABLEmyisamchk来对一个表整理碎片。如果在一个表中有你频繁访问或改变的固定长度列,表中也有一些可变长度列,仅为避免碎片而把这些可变长度列移到其它表可能是一个好主意。

动态格式表的一般特征:

·         除了长度少于4的列外,所有的字符串列是动态的。

·         在每个记录前面是一个位图,该位图表明哪一列包含空字符串(对于字符串列)或者0(对于数字列)。注意,这并不包括包含NULL值的列。如果一个字符列在拖曳空间移除后长度为零,或者一个数字列为零值,这都在位图中标注了且列不被保存到磁盘。 非空字符串被存为一个长度字节加字符串的内容。

·         通常比固定长度表需要更少的磁盘空间。

·         每个记录仅使用必需大小的空间。尽管如此,如果一个记录变大,它就按需要被分开成多片,造成记录碎片的后果。比如,你用扩展行长度的信息更新一行,该行就变得有碎片。在这种情况下,你可以时不时运行OPTIMIZE TABLEmyisamchk -r来改善性能。可使用myisamchk -ei来获取表的统计数据。

·         动态格式表在崩溃后要比静态格式表更难重建,因为一个记录可能被分为多个碎片且链接(碎片)可能被丢失。

·         动态尺寸记录期望的行长度用下列表达式来计算:

·                3

·                + (number of columns + 7) / 8

·                + (number of char columns)

·                + (packed size of numeric columns)

·                + (length of strings)

·                + (number of NULL columns + 7) / 8

对每个链接需要额外的6字节。在一个更新导致一个记录的扩大之时,一个动态记录被链接了。每个新链接至少是20字节,所以下一个扩大可能在同样的链接里进行。如果不是,则另一个链接将被建立。你可以使用myisamchk -ed来找出链接的数目。所有的链接可以用myisamchk -r来移除。

15.1.3.3. 已压缩表特征

已压缩存储格式是由myisampack工具创建的只读格式。

所有MySQL分发版里都默认包括myisampack。已压缩表可以用myisamchk来解压缩。

已压缩表有下列特征:

·         已压缩表占据非常小的磁盘空间。这最小化了磁盘用量,当使用缓慢的磁盘(如CD-ROM)之时,这是很有用的。

·         每个记录是被单独压缩的,所以只有非常小的访问开支。依据表中最大的记录,一个记录的头在每个表中占据13个字节。每个列被不同地压缩。通常每个列有一个不同的Huffman树。一些压缩类型如下:

o        后缀空间压缩。

o        前缀空间压缩。

o        零值的数用一个位来存储。

o        如果在一个整型列中的值有一个小的范围,列被用最小可能的类型来存储。比如,一个BIGINT列(8字节),如果所有它的值在-128127范围内,它可以被存储为TINYINT列(1字节)

o        如果一个列仅有一小组可能的值,列的类型被转化成ENUM

o        一个列可以使用先前压缩类型的任意合并。

·         可以处理固定长度或动态长度记录。

 

MyISAM表方面的问题

MySQL用来存储数据的文件格式已经被广泛测试过,但总是有导致数据表变得损坏的环境。

15.1.4.1. 损坏的MyISAM

即使MyISAM表格式非常可靠(SQL语句对表做的所有改变在语句返回之前被写下),如果下列任何事件发生,你依然可以获得损坏的表:

·         mysqld进程在写中间被杀掉。

·         发生未预期的计算机关闭(例如,计算机被关闭)。

·         硬件故障。

·         你可以同时在正被服务器修改的表上使用外部程序(如myisamchk)。

·         MySQLMyISAM代码的软件缺陷。

一个损坏的表的典型症状如下:

·         当在从表中选择数据之时,你得到如下错误:

·                Incorrect key file for table: '...'. Try to repair it

·         查询不能在表中找到行或返回不完全的数据。

你可以用CHECK TABLE statement语句来检查MyISAM表的健康,并用REPAIR TABLE修复一个损坏的MyISAM表。当mysqld不运行之时,你也可以用myisamchk命令检查或修理一个表。

如果你的表变得频繁损坏,你应该试着确定为什么会这样的原因。要明白的最重要的事是表变得损坏是不是因为服务器崩溃的结果。你可以在错误日志中查找最近的restarted mysqld消息来早期验证这个。如果存在这样一个消息,则表损坏是服务器死掉的一个结果是很有可能的。否则,损坏可能在正常操作中发生。这是一个缺陷。你应该试着创建一个展示这个问题的可重复生成的测试案例。

 

15.1.4.2. 未被适当关闭的表的问题

每个MyISAM索引文件(.MYI)在头有一个计数器,它可以被用来检查一个表是否被恰当地关闭。如果你从CHECK TABLEmyisamchk得到下列警告,意味着这个计数器已经不同步了:

clients are using or haven't closed the table properly

这个警告并不是完全意味着表已被破坏,但你至少应该检查表。

计数器的工作方式如下:

·         表在MySQL中第一次被更新,索引文件头的计数器加一。

·         在未来的更新中,计数器不被改变。

·         当表的最后实例被关闭(因为一个操作FLUSH TABLE或因为在表缓冲区中没有空间)之时,若表已经在任何点被更新,则计数器减一。

·         当你修理或检查表并且发现表完好之时,计数器被重置为零。

·         要避免与其它可能检查表的进程进行事务的问题,若计数器为零,在关闭时计数器不减一。

换句话来说,计数器只有在下列情况会不同步:

·         MyISAM表不随第一次发出的LOCK TABLESFLUSH TABLES被复制。

·         MySQL在一次更新和最后关闭之间崩溃(注意,表可能依然完好,因为MySQL总是在每个语句之间为每件事发出写操作)。

·         一个表被myisamchk --recovermyisamchk --update-state修改,同时被mysqld使用。

·         多个mysqld服务器正使用表,并且一个服务器在一个表上执行REPAIR TABLECHECK TABLE,同时该表也被另一个服务器使用。在这个结构中,使用CHECK TABLE是安全的,虽然你可能从其它服务器上得到警告。尽管如此,REPAIR TABLE应该被避免,因为当一个服务器用一个新的数据文件替代旧的之时,这并没有发送信号到其它服务器上。

总的来说,在多服务器之间分享一个数据目录是一个坏主意。
Godisu推荐阅读:
  评论这张
 
阅读(715)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017