前面提到,我们有个云文档项目的快照内容是直接存储到db的,属于大文本存储,文档快照的内容字段大部分都是kb级别,部分甚至到MB级别。目前对于数据的读取,已经进行了CDN缓存优化(静态资源缓存利器——CDN),对于数据的写入和存储还有待优化,如果可以通过一些压缩算法在大文本进行压缩存储,可以在很大程度上节省DB的存储空间,缓解DB的I/O压力。
select table_name as '表名', table_rows as '记录数', truncate(data_length/1024/1024, 2) as '数据容量(MB)', truncate(index_length/1024/1024, 2) as '索引容量(MB)', truncate(DATA_FREE/1024/1024, 2) as '碎片占用(MB)' from information_schema.tables where table_schema=${数据库名} order by data_length desc, index_length desc;
我们都知道innodb的页块默认大小为16k,如果表中一行数据长度超出了16k,就会出现行溢出,溢出的行是存放在另外的地方(uncompress blob page)。由于innodb采用聚簇索引把数据进行存放起来,即B+Tree结构,因此每个页块中至少有两行数据,否则就失去了B+Tree的意义,这样就得出一行数据最大的长度限制为8k(大字段在数据页会存储768个字节数据,剩余的数据溢出到另外的页中,数据页还有20个字节记录溢出页的地址)
文件空洞部分不占用磁盘空间、文件所占用的磁盘空间仍然是连续的
适用场景:由于数据量太大,磁盘空间不足,负载主要体现在IO上,而服务器的CPU又有比较多的余量的场景。
相关文档:dev.mysql.com/doc/refman/…
相关文档:dev.mysql.com/doc/refman/…
空洞
特性)ALTER TABLE xxx COMPRESSION = ZLIB
可以启用TPC页压缩功能,但这只是对后续增量数据进行压缩,如果期望对整个表进行压缩,则需要执行 OPTIMIZE TABLE xxx
实现过程:一个压缩页在缓冲池中都是一个16K的非压缩页,只有在数据刷盘的时候,会进行一次压缩,压缩后剩余的空间会用 0x00 填满,利用文件系统的空洞特性(hole punch)对文件进行裁剪,释放 0x00 占用的稀疏空间
MySQL目前没有直接针对列压缩的方案,有一个曲线救国的方法,就是在业务层使用MySQL提供的压缩和解压函数来针对列进行压缩和解压操作。也就是如果需要对某一列做压缩,在写入时调用COMPRESS
函数对那个列的内容进行压缩,读取的时候,使用UNCOMPRESS
函数对压缩过的数据进行解压。
COMPRESS()
UNCOMPRESS()
LENGTH()
UNCOMPRESSED_LENGTH()
insert into xxx (content) values (compress('xxx....'))
读取压缩的数据:select c_id, uncompressed_length(c_content) uncompress_len, length(c_content) compress_len from xxx
SELECT NAME, FS_BLOCK_SIZE, FILE_SIZE, ALLOCATED_SIZE FROM information_schema.INNODB_TABLESPACES WHERE NAME like 'test_compress%';
FS_BLOCK_SIZE
:文件系统块大小,也就是打孔使用的单位大小FILE_SIZE
:文件的表观大小,表示文件的最大大小,未压缩ALLOCATED_SIZE
:文件的实际大小,即磁盘上分配的空间量压缩率:
【相关推荐:mysql视频教程】
以上是MySQL中怎么进行大文本存储压缩的详细内容。更多信息请关注PHP中文网其他相关文章!