首页 > 代码库 > 【深入浅出Mysql】MySql存储引擎之MyISAM(二)

【深入浅出Mysql】MySql存储引擎之MyISAM(二)

一、MyISAM

   1.1 数据存储

  MyISAM是默认的MySQL插件式存储引擎。它不支持事务和外键。
优势:访问速度快,基本上以SELECT、INSERT为主的应用基本上都可以使用这个引擎来创建表。
每个MyISAM在磁盘上存储称3个文件,其文件名和表名相同,扩展名不同,分别是:
  • .frm(存储表自定义)
  • .MYD(MYDATA,存储数据)
  • .MYI(MYIndex,存储索引)
  MyISAM的数据文件和索引文件可以放置在不同的目录,平均分布IO,获得更快的速度。其中索引文件需要在创建表的时候通过DATA DIRECTORY和INDEX DIRECTORY语句指定。
注意:文件路径需要是绝对路径,并且具有访问权限。

MyISAM表又支持3种不同的存储格式,分别是:

  • 静态表
  • 动态表
  • 压缩表

   1.1.1 静态表

  静态表是默认的存储格式。静态表中的字段都是非变长字段,每个记录都是固定长度的。静态表的优缺点如下:
优点:
 
1
存储快、易缓存。
  
2
 由于每个记录位置固定,崩溃后容易重建

缺点:
   
1
占用的空间比动态表多。

注意:静态表的数据在存储时会按照列的宽度补足空格,但是我们从数据库读取的时候是不会拿到这个空格的。如果需要保存的内容后面本身是带空格的,也会在返回结果前被去掉。另外一点是如果空格是在内容前面或中间是不会被去掉的。
例如:
首先创建一个测试表test,分别插入4条不同数据。如下:
CREATE TABLE `test` (
  `name` varchar(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=gbk
insert into test values(‘小毛驴‘);
insert into test values(‘小毛驴 ‘);
insert into test values(‘ 小毛驴‘);
insert into test values(‘小 毛驴‘);
执行查询sql语句:select name,length(name) from test; 运行结果如下:
技术分享

从上面的结果可以看出,第二条插入在小毛驴后面的空格被去掉了而前面的空格保留了下来!

   1.1.2 动态表

    什么是动态表呢?如果表中存在varchar、blob、text字段,表类型就是动态了。动态表是字段长度不固定,占用空间比静态表小,但频繁的更新删除记录容易产生碎片,需要定期执行OPTIMIZE TABLE语句或MYISAMACHK -r 命令来改善性能,并且出现故障的时候恢复相对比较困难。可使用myisamchk -ei来获取表的统计数据。
优点:
   
1
 占用空间小。每条记录都有一个header,作用就是表明该记录有多长,所有的字符串列都是动态的(除非小于4个字节,这种情况下,节省的空间可以忽略不计,增加的复杂度反而会导致性能丢失)
缺点:
   
1
 容易产生碎片。例如:更新了用户名‘小毛驴‘为‘小毛驴帅‘,帅不能立刻就出现在驴的后面,因为空间被其他记录占用,对于出现碎片的列,每个新连接会损失6个字节。如果碎片严重,有可能出现库爆炸。
   
2
 出现故障恢复难。
  不包括连接的动态记录的空间消耗可以用下面的公式计算:
3+(列数+7)/8+(字符列数)+数字列的打包尺寸+字符串长度+(空列的数量+7)/8
每条记录的header可以表明那个字符串列是空的,那个数字列包含0(非空),在那种情况下不向磁盘存储,非空字符串包含一个长度字节加上字符串内容。

   1.1.3 压缩表

    MySQL分发版本里默认包含myisampack工具,占据非常小的磁盘空间。因为每个记录时被单独压缩的,已压缩存储格式是由它创建的只读格式。如果使用表压缩技术,要先确认innodb_file_per_table=1,以及innodb_file_format=Barracuda。

SET GLOBAL innodb_file_per_table=1;
SET GLOBAL innodb_file_format=Barracuda;
CREATE TABLE t1
 (c1 INT PRIMARY KEY) 
 ROW_FORMAT=COMPRESSED  
 KEY_BLOCK_SIZE=8;
  • 如果你指定ROW_FORMAT=COMPRESSED,那么可以忽略KEY_BLOCK_SIZE的值,这时使用默认innodb页的一半,即8kb;
  • 如果你指定了KEY_BLOCK_SIZE的值,那么你可以忽略ROW_FORMAT=COMPRESSED,因为这时会自动启用压缩;
  • 为了指定最合适KEY_BLOCK_SIZE的值,你可以创建表的多个副本,使用不同的值进行测试,比较他们的.ibd文件的大小;
  • KEY_BLOCK_SIZE的值作为一种提示,如必要,Innodb也可以使用一个不同的值。0代表默认压缩页的值,Innodb页的一半。KEY_BLOCK_SIZE的值只能小于等于innodb page size。如果你指定了一个大于innodb page size的值,mysql会忽略这个值然后产生一个警告,这时KEY_BLOCK_SIZE的值是Innodb页的一半。如果设置了innodb_strict_mode=ON,那么指定一个不合法的KEY_BLOCK_SIZE的值是返回报错。
  InnoDB未压缩的数据页是16K,根据选项组合值,mysql为每个表的.ibd文件使用1kb,2kb,4kb,8kb,16kb页大小,实际的压缩算法并不会受KEY_BLOCK_SIZE值影响,这个值只是决定每个压缩块有多大,从而影响多少行被压缩到每个页。设置KEY_BLOCK_SIZE值等于16k并不能有效的进行压缩,因为默认的innodb页就是16k,但是对于拥有很多BLOB,TEXT,VARCHAR类型字段的表可能会有效果的。
优点:
   
1
 压缩表占据很小的磁盘空间,从而减少磁盘的I/O,还能提高系统吞吐量。对于读比重多的应用,压缩是特别有用。压缩能够让系统拥有足够的内存来存储热数据。   
   
2
 每个记录被单独压缩,访问开支小。
   
3
 可以处理固定长度或动态长度记录。

缺点:
   

1
 耗费较多的CPU资源
什么时候使用压缩表,这取决于你的负载和数据集合,或者特定的配置,可以考虑如下因素:
1、表中有较多重复的字符串
2、已经在应用中压缩过的数据,不适合存储到压缩表中。
3、对于如何压缩表才算最好的,MySQL没有明确的定义,所以压缩后一定要通过like或order by来测试压缩后的索引性能
4、在应用中进行压缩的,不适合再进行表压缩
5、在表上的workload是一个关键性因素,如果更新主要作用在外部存储的长字符串的非索引列上,压缩的开销可能是可以接受的。如果你的负载是I/O bound而非CPU bound的,压缩可能会改善整体性能
6、压缩可以通过消耗CPU来减少IO,如果IO是相对紧缺的资源时,会获得更好的效果
7、选择压缩Page的大小应该比记录更大,否则可能会引起大量的压缩失败,通常情况下key_block_size=8是比较安全的设置
更多关于表压缩内容:http://www.cnblogs.com/mysql-dba/p/5125220.html

    MyISAM表可能会损坏可以使用语句:repair table来修复。如果修复不好,检查是否其它文件有损坏。如:索引文件坏了。

参考资料
http://blog.csdn.net/horace20/article/details/6773761
http://blog.chinaunix.net/uid-31137082-id-5709530.html
深入浅出MySQL

作者:小毛驴,一个游戏人 
梦想:世界和平   
原文地址:http://blog.csdn.net/liulongling
若有错误之处,请多多谅解并欢迎批评指正。    
本博客中未标明转载的文章归作者小毛驴所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

【深入浅出Mysql】MySql存储引擎之MyISAM(二)