1、客户端和服务器之间传输的数据量太大,需要进行压缩,节约带宽
2、某个列的数据量大,只针对某个列的数据压缩
3、表数据太多,需要将表数据压缩存放,减少磁盘空间的占用
MySQL 的压缩协议解决网络传输数据量大
适用场景
查询大量数据,带宽不够(比如导出数据)
复制的时候 binlog 量太大,启用 slave_compressed_protocol 参数进行日志压缩复制。
前置条件
MySQL 服务器端和客户端都支持 zlib 算法。启动压缩协议会导致 CPU 负载略微上升。
MySQL 为了较少 CPU 开销而做的一个优化。如果内容小于 50 个字节的时候,就不对内容进行压缩,而大于 50 字节的时候,才会启用压缩功能。
使用示例
# 在客户端连接的时候加上-C 或者--compress=true
mysql -uroot -p123qqq...A -h127.0.0.1 --compress
mysqldump -uroot -p123qqq...A -h127.0.0.1 -default-character-set=utf8 --compress --single-transaction dbname tablename > tablename.sql
# 如果需要在主从复制中启用压缩传输,则在从机开启 slave_compressed_protocol=1
MySQL压缩&解压函数解决字段数据量大
说明及适用场景
MySQL 针对列的压缩目前直接的方案并不支持,但是可以通过在业务层面使用 MySQL 提供的压缩和解压函数来针对列进行压缩和解压操作。
针对 MySQL 中某个列或者某几个列数据量特别大,一般都是 varchar、text、char 等数据类型。
前置条件
使用该函数需要 MySQL 服务端支持压缩,否则会返回 NULL
压缩字段好采用 varbinary 或者 blob 字段类型保存。使用 UNCOMPRESSED 函数对压缩过的数据进行解压。注意,采用这种方式需要在业务侧做少量改造。压缩后的内容存储方式如下:
a、空字符串就以空字符串存储
b、非空字符串存储方式为前 4 个 bype 保存未压缩的字符串,紧接着保存压缩的字符串
使用示例
相关函数
压缩函数
COMPRESS()
解压缩函数
UNCOMPRESS()
字符串长度函数
LENGTH()
未解压字符串长度函数
UNCOMPRESSED_LENGTH()
创建一张测试表
CREATE TABLE IF NOT EXISTS `test_compress` (
`id` int unsigned NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'ID',
`content` blob NOT NULL COMMENT '内容'
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='压缩测试表';
-- 插入压缩的数据
insert into `test_compress`(content) values(COMPRESS(REPEAT('a',1000)));
-- 读取压缩的数据
select UNCOMPRESS(content) from `test_compress`;
-- 查询对应的长度和内容
SELECT UNCOMPRESSED_LENGTH(content) AS length, LENGTH(content) AS compress_length, UNCOMPRESS(content), content FROM `test_compress`\G;
从上面截图可以看出压缩效果比较好,针对 text、char、varchr、blob 等,如果里面重复的数据越多压缩效果就越好。
存储引擎表压缩解决磁盘占用量大
目前 myisam、innodb、tokudb、MyRocks 等引擎都支持表的压缩
InnoDB(针对MariaDB Server10.6.1测试)
前提条件
innodb_file_per_table=1
innodb_file_format=Barracuda
MariaDB 10.2.2以前,默认为Antelope
MariaDB 10.2.2以后,默认为Barracuda
MariaDB 10.3.1开始,移除
行格式改动
# Dynamic
MariaDB [xxl_job]> system du -sh /data/mysql_data/xxl_job/xxl_job_log.ibd
2.4G /data/mysql_data/xxl_job/xxl_job_log.ibd
MariaDB [xxl_job]> SHOW TABLE STATUS FROM xxl_job WHERE Name='xxl_job_log'\G
*************************** 1. row ***************************
...
Row_format: Dynamic
...
# 更改为COMPRESSED
MariaDB [xxl_job]> set GLOBAL innodb_read_only_compressed=;
MariaDB [xxl_job]> ALTER TABLE xxl_job.xxl_job_log ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
MariaDB [xxl_job]> system du -sh /data/mysql_data/xxl_job/xxl_job_log.ibd
1.3G /data/mysql_data/xxl_job/xxl_job_log.ibd
# 但是到这里时,我遇到了问题,我不知道怎么再将COMPRESSED转回Dynamic。问题先记录,后面解决
参考:
• https://cloud.tencent.com/developer/article/1005252
• https://mariadb.com/kb/en/innodb-row-formats-overview/#dynamic-row-format