记得一次面试中,面试官问我是否知道表的压缩,这个时候我才知道mysql有个表压缩这么个功能,今天试用下看看表的压缩率怎么样。
这里分两个部分说明,第一部分:官方文档说明;第二部分:具体实例测试。
【第一部分】
一、表压缩概述:
表压缩可以在创建表时开启,压缩表能够使表中的数据以压缩格式存储,压缩能够显著提高原生性能和可伸缩性。压缩意味着在硬盘和内存之间传输的数据更小且占用相对少的内存及硬盘,对于辅助索引,这种压缩带来更加明显的好处,因为索引数据也被压缩了。压缩对于硬盘是SSD的存储设备尤为重要,因为它们相对普通的HDD硬盘比较贵且容量有限。
我们都知道,CPU和内存的速度远远大于磁盘,因为对于数据库服务器,磁盘IO可能会成为紧要资源或者瓶颈。数据压缩能够让数据库变得更小,从而减少磁盘的I/O,还能提高系统吞吐量,以很小的成本提高CPU的利用率。对于读比重比较多的应用,压缩是特别有用。压缩能够让系统拥有足够的内存来存储热数据。
在创建innodb表时带上ROW_FORMAT=COMPRESSED参数能够使用比默认的16K更小的页。这样在读写时需要更少的I/O,对于SSD磁盘更有价值。
页的大小通过KEY_BLOCK_SIZE
参数指定。不同大小的页意味着需要使用独立表空间,不能使用系统共享表空间,可以通过innodb_file_per_table
指定。KEY_BLOCK_SIZE
的值越小,你获得I/O好处就越多,但是如果因为你指定的值太小,当数据被压缩到不足够满足每页多行数据记录时,会产生额外的开销来重组页。对于一个表,KEY_BLOCK_SIZE
的值有多小是有严格的限制的,一般是基于每个索引键的长度。有时指定值过小,当create table或者alter table会失败。
在缓冲池中,被压缩的数据是存储在小页中的,这个小页的实际大小就是KEY_BLOCK_SIZE
的值。为了提取和更新列值,mysql也会在缓冲池中创建一个未压缩的16k页。任何更新到未压缩的页也需要重新写入到压缩的页,这时你需要估计缓冲池的大小以满足压缩和未压缩的页,尽管当缓冲空间不足时,未压缩的页会被挤出缓冲池。在下次访问时,不压缩的页还会被创建。
二、使用表的压缩
在创建一个压缩表之前,需要启用独立表空间参数innodb_file_per_table=1;也需要设置
innodb_file_format
=Barracuda,你可以写到my.cnf文件中不需要重启mysql服务。
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类型字段的表可能会有效果的。
三、InnoDB表的压缩优化
原文:http://www.cnblogs.com/mysql-dba/p/5125220.html