功能介绍
当前有针对行格式的压缩和针对数据页面的压缩,但是这两种压缩方式在处理一个表中的某些大字段和其他很多小字段,同时对小字段的读写很频繁,对大字段访问不频繁的情形中,在读写访问时都会造成很多不必要的计算资源的浪费。
列压缩功能可以压缩那些访问不频繁的大字段而不压缩那些访问频繁的小字段,这样不仅能够减少整行字段的存储空间,而且可以提高读写访问的效率。
例如,一张员工表:
create table employee(id int, age int, gender boolean, other varchar(1000) primary key (id))
,当对 id,age,gender
小字段访问比较频繁,而对 other
大字段的访问频率比较低时,可以将 other
列创建为压缩列。一般情况下,只有对 other
的读写才会触发对该列的压缩和解压,对其他列的访问并不会触发该列的压缩和解压。由此进一步降低了行数据存储的大小,使得对访问频繁的小字段能够实现更快访问,对访问频率比较低的大字段的存储空间能够实现进一步降低。说明:
参数 cdb_column_compression_enabled 为列压缩功能的开关。
MySQL5.7的列压缩功能默认为关闭状态,如需使用请 提交工单 开启。
MySQL8.0内核版本20221215及以上的列压缩功能为默认开启。
由于云数据库 MySQL8.0 版本采用了开源协同版本的列压缩能力,和 MySQL5.7 版本列压缩的实现有所不同,下面将分别为您介绍两个版本的列压缩能力的使用说明,您可点击“MySQL5.7列压缩”或“MySQL8.0列压缩”切换了解。
支持版本
内核版本 MySQL5.7 20210330及以上
适用场景
表中有某些大字段和其他很多小字段,同时对小字段的读写很频繁,对大字段访问不频繁的情形中,可以将大字段设置为压缩列。
使用说明
支持的数据类型
1.
BLOB
(包含 TINYBLOB
、MEDIUMBLOB
、LONGBLOB
)2.
TEXT
(包含 TINYTEXT
、MEDIUMTEXT
、LONGTEXT
)3.
VARCHAR
4.
VARBINARY
注意:
支持的 DDL 语法类型
column_definition:data_type [NOT NULL | NULL] [DEFAULT default_value][AUTO_INCREMENT] [UNIQUE [KEY]] [[PRIMARY] KEY][COMMENT 'string'][COLLATE collation_name][COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}|COMPRESSED=[zlib]] # COMPRESSED 压缩列关键字[STORAGE {DISK|MEMORY}][reference_definition]
一个简单的示例如下:
CREATE TABLE t1(id INT PRIMARY KEY,b BLOB COMPRESSED);
此时省略了压缩算法,默认选择
zlib
压缩算法 ,您也可以显示指定压缩算法关键字,目前只支持 zlib
压缩算法。CREATE TABLE t1(id INT PRIMARY KEY,b BLOB COMPRESSED=zlib);
支持的 DDL 语法总结如下:
create table 方面:
DDL | 是否继承压缩属性 |
CREATE TABLE t2 LIKE t1; | Y |
CREATE TABLE t2 SELECT * FROM t1; | Y |
CREATE TABLE t2(a BLOB) SELECT * FROM t1; | N |
alter table 方面:
DDL | 描述 |
ALTER TABLE t1 MODIFY COLUMN a BLOB; | 将压缩列变为非压缩列 |
ALTER TABLE t1 MODIFY COLUMN a BLOB COMPRESSED; | 将非压缩列变为压缩列 |
参数说明
参数名 | 动态 | 类型 | 默认 | 参数值范围 | 说明 |
cdb_column_compression_enabled | Yes | bool | FALSE | TRUE/FALSE | 列压缩的开关,关闭后,不允许建有压缩属性的表,已有压缩属性的表不受影响。 |
innodb_column_compression_zlib_wrap | Yes | bool | TRUE | TRUE/FALSE | 如果打开,将生成数据的 zlib 头和 zlib 尾并做 adler32 校验 |
innodb_column_compression_zlib_strategy | Yes | Integer | 0 | [0,4] | 列压缩使用的压缩策略,最小值为:0,最大值为4,0 - 4分别和 zlib 中的压缩策略 Z_DEFAULT_STRATEGY、Z_FILTERED、Z_HUFFMAN_ONLY、Z_RLE、Z_FIXED 一一对应。 一般来说,Z_DEFAULT_STRATEGY 对于文本数据常是最佳的,Z_RLE 对于图像数据来说是最佳的 |
innodb_column_compression_zlib_level | Yes | Integer | 6 | [0,9] | 列压缩使用的压缩级别,最小值:0,最大值:9,0代表不压缩,该值越大代表压缩后的数据越小,但压缩时间也越长 |
innodb_column_compression_threshold | Yes | Integer | 256 | [0, 0xffffffff] | 列压缩使用的压缩阈,最小值为:1,最大值为:0xffffffff,单位:字节。只有长度大于或等于该值数据才会被压缩,否则原数据保持不变,只是添加压缩头 |
innodb_column_compression_pct | Yes | Integer | 100 | [1, 100] | 列压缩使用的压缩率,最小值:1,最大值:100,单位:百分比。只有压缩后数据大小 / 压缩前数据大小低于该值时,数据才会被压缩,否则原数据保持不变,只是添加压缩头 |
说明:
新增状态说明
名称 | 类型 | 说明 |
Innodb_column_compressed | Integer | 列压缩的压缩次数,包括非压缩格式和压缩格式两种状态的压缩 |
Innodb_column_decompressed | Integer | 列压缩的解压次数,包括非压缩格式和压缩格式两种状态的解压缩 |
新增错误说明
名称 | 范围 | 说明 |
Compressed column '%-.192s' can't be used in key specification | 指定压缩的列名 | 不能对有索引的列指定压缩属性 |
Unknown compression method: %s | 在 DDL 语句中指定的压缩算法名 | 在 create table 或者 alter table 时指定 zlib 之外非法的压缩算法 |
Compressed column '%-.192s' can't be used in column format specification | 指定压缩的列名 | 在同一个列中,已经指定 COLUMN_FORMAT 属性就不能再指定压缩属性,其中 COLUMN_FORMAT 只在 NDB 中被使用 |
Alter table ... discard/import tablespace not support column compression | \\ | 带有列压缩的表不能执行 Alter table ... discard/import tablespace 语句 |
性能
整体性能分为 DDL 和 DML 两方面:
DDL 方面,使用 sysbench 进行测试:
列压缩对 COPY 算法的 DDL 有较大的性能影响,压缩后性能表现比之前慢7倍 - 8倍。
对于 inplace 的影响则取决于压缩后的数据量大小,如果采用压缩后,整体数据大小有降低,那么 DDL 的性能是有提升;反之,性能会有一定的降幅。
对于 instant 来说,列压缩对该类型的 DDL 基本没有影响。
DML 方面:考虑最常见的压缩情形(压缩比1:1.8),此时有8个列的表,表中有一个大的 varchar 类型的列,其插入数据长度在1 - 6000内均匀随机,插入的字符在0 - 9 、a - b内随机,其他几个列数据类型为 char(60) 或 int 类型。此时其对非压缩列插入、删除和查询都有10%以内的提升,但对于非压缩列的更新则有10%以内的下降,对于压缩列的更新则有15%以内的性能跌幅。这是因为在更新过程中,MySQL 会先读出该行的值然后再写入该行更新之后的值,整个更新过程会触发一次解压和压缩而插入和查询只会进行一次压缩或者解压。
注意事项
1. 逻辑导出方面,逻辑导出时 create table 还是会附有 Compressed 相关的关键字。因此导入时在云数据库 MySQL 内部是支持的。其他 MySQL 分支以及官方版本:
官方版本号小于5.7.18,可以直接导入。
官方版本号大于或等于5.7.18,需要在逻辑导出之后,去掉压缩关键字。
2. DTS 导出其他云或是用户时,在 binlog 同步过程中可能会出现不兼容的问题,可以跳过带压缩关键字的 DDL 语句。
支持版本
内核版本 MySQL8.0 20221215及以上
适用场景
表中有某些大字段和其他很多小字段,同时对小字段的读写很频繁,对大字段访问不频繁的情形中,可以将大字段设置为压缩列。
使用说明
支持的数据类型
1.
BLOB
(包含 TINYBLOB
、MEDIUMBLOB
、LONGBLOB
)2.
TEXT
(包含 TINYTEXT
、MEDIUMTEXT
、LONGTEXT
)3.
VARCHAR
4.
VARBINARY
5.
JSON
语法如下:
CREATE TABLE t1(id INT PRIMARY KEY,b BLOB COMPRESSED);
或者
CREATE TABLE t1(id INT PRIMARY KEY,b BLOB COLUMN_FORMAT COMPRESSED);
压缩阈值(Threshold)
压缩阈值通过参数 innodb_min_column_compress_length 控制,默认为256。如果列的原 size 超过此参数的取值,则进行压缩,否则只添加压缩 header,不对数据进行实际压缩。
支持的 DDL 语法总结如下:
create table 方面:
DDL | 是否继承压缩属性 |
CREATE TABLE t2 LIKE t1; | Y |
CREATE TABLE t2 SELECT * FROM t1; | N |
CREATE TABLE t2(a BLOB) SELECT * FROM t1; | N |
alter table 方面:
DDL | 描述 |
ALTER TABLE t1 MODIFY COLUMN a BLOB; | 将压缩列变为非压缩列 |
ALTER TABLE t1 MODIFY COLUMN a BLOB COMPRESSED; | 将非压缩列变为压缩列 |
参数说明
参数名 | 动态 | 类型 | 默认 | 参数值范围 | 说明 |
innodb_zlib_column_compression_level | Yes | UINT | 6 | [0-9] | zlib 压缩,0表示不压缩,1表示最快的压缩,9表示压缩程度最大的压缩,从1到9压缩速度越慢,但压缩率越高。 |
innodb_zstd_column_compression_level | Yes | UINT | 3 | [1-22] | zstd 压缩,1表示最快的压缩,22表示压缩程度最大的压缩,从1到22压缩速度越慢,但压缩率越高。 |
innodb_min_column_compress_length | Yes | UINT | 256 | [1,UINT_MAX32] | 控制压缩阈值,单位:字节,如果列的原长度大于或等于此参数的取值,则进行压缩,否则只添加压缩 header,实际不对数据进行压缩。 |
多算法支持(Multiple Algorithms)
云数据库 MySQL8.0版本支持 ZLIB、LZ4、ZSTD 三种压缩算法。也可以省略算法,省略后将默认算法为 ZLIB。
语法如下:
CREATE TABLE t1(id INT PRIMARY KEY,b BLOB COMPRESSED ALGORITHM = [ZLIB|LZ4|ZSTD]);
或者
CREATE TABLE t1(id INT PRIMARY KEY,b BLOB COLUMN_FORMAT COMPRESSED ALGORITHM = [ZLIB|LZ4|ZSTD]);
压缩算法与压缩程度选择(Compression Algorithms and Compression Levels)
1. ZLIB:目前提供了 ZLIB 的多压缩级别,参数为 innodb_zlib_column_compression_level,值为0-9,其中0表示不压缩,1表示最快的压缩,9表示压缩程度最大的压缩,默认为6。
2. LZ4:与 MySQL 的 Page 压缩保持一致,不支持 LZ4 的多程度压缩,使用 LZ4 压缩算法时需要注意,LZ4 压缩的最大原始长度为231-1,而 LONGBLOB 的最大长度为232-1,当压缩的原始数据长度大于等于231时,将会隐式地使用 ZLIB 进行压缩。
3. ZSTD:ZSTD 即 ZStandard 有三种压缩方式。此处列压缩支持的是不含字典的非 streaming 的普通压缩,提供了多压缩级别,参数为 innodb_zstd_column_compression_level,值为1-22,1表示最快的压缩,22表示压缩程度最大的压缩,默认为3。
压缩属性显示
这里展示默认压缩算法:ALGORITHM = ZLIB。
CREATE TABLE t2 (a VARCHAR(100) COMPRESSED) ENGINE=InnoDB;SHOW CREATE TABLE t2;
注意事项
1. 逻辑导出方面,逻辑导出时 create table 还是会附有 Compressed 相关的关键字。因此导入时在云数据库 MySQL 内部是支持的。其他 MySQL 分支以及官方版本:
官方版本号小于8.0.22,可以直接导入。
官方版本号大于或等于8.0.22,需要在逻辑导出之后,去掉压缩关键字。
2. DTS 导出其他云或者用户时,在 binlog 同步过程中可能会出现不兼容的问题,此时可以跳过带压缩关键字的 DDL 语句。
3. 物理备份方面,由于备份时其字段在 innodb 内部是已经压缩的状态,因此使用该备份的版本也必须是带有列压缩的版本。
4. 不支持 MySQL5.7到 MySQL8.0的物理升级。