字段压缩
为了减少数据页面存储空间占用,节省成本,GaussDB(for MySQL)推出细粒度的字段压缩,提供ZLIB和ZSTD两种压缩算法,用户可以综合考虑压缩比和压缩解压性能影响,选择合适的压缩算法,对不频繁访问的大字段进行压缩。同时,字段压缩特性提供自动压缩的能力,帮助用户更方便地使用此特性。
使用场景:降本,表中包含不频繁访问的大字段。
使用须知
- GaussDB(for MySQL)实例内核版本大于等于2.0.54.240600可使用该功能。
- 不支持分区表、临时表、非InnoDB引擎表。
- 压缩字段上不能包含索引(主键、唯一索引、二级索引、外键、全文索引)。
- 仅支持的数据类型:BLOB(包含TINYBLOB、BLOB、MEDIUMBLOB、LONGBLOB),TEXT(包含TINYTEXT、TEXT、MEDIUMTEXT、LONGTEXT),VARCHAR,VARBINARY。
- 不支持在生成列上使用此特性。
- 不支持在分区表和带有压缩字段的表之间执行EXCHANGE PARTITION式语句。
- 不支持IMPORT TABLESPACE。
- 仅支持在CREATE TABLE/ALTER TABLE ADD/ALTER TABLE CHANGE/ALTER TABLE MODIFY场景使用此特性。
- ALTER TABLE ADD COLUMN不支持INSTANT算法,ALTER TABLE {CHANGE|MODIFY} 语法涉及数据变化时不支持使用INSTANT算法。
- 自动压缩场景(rds_column_compression=2),定义字段的最大长度需大于等于字段压缩阈值(rds_column_compression_threshold)时才可以被添加压缩属性;显式压缩场景(rds_column_compression=1),若定义压缩字段的最大长度小于字段压缩阈值,字段仍可被添加压缩属性,同时收到warning信息。
- 若当前表中包含压缩字段,暂不支持NDP计算下推。
- 客户手动拉取BINLOG同步过程中ALTER语句会出现不兼容的问题,推荐客户侧使用HINT的方式来解决。
- 利用DRS迁移至无该特性的实例,压缩属性被消除。全量迁移任务可以进行,增量迁移时ALTER语句中存在压缩字段会导致迁移任务失败。
- 物理备份方面,利用备份去做数据恢复的版本也必须是带有字段压缩特性的。
- 升级至新版本之后,如果已经使用字段压缩功能,不支持回退至无该特性的版本。
语法
扩展column_definition定义,支持在CREATE TABLE/ALTER TABLE ADD/ALTER TABLE CHANGE/ALTER TABLE MODIFY场景定义列属性时使用压缩特性。
create_definition: { col_name column_definition | {INDEX | KEY} [index_name] [index_type] (key_part,...) [index_option] ... | {FULLTEXT | SPATIAL} [INDEX | KEY] [index_name] (key_part,...) [index_option] ... | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (key_part,...) [index_option] ... | [CONSTRAINT [symbol]] UNIQUE [INDEX | KEY] [index_name] [index_type] (key_part,...) [index_option] ... | [CONSTRAINT [symbol]] FOREIGN KEY [index_name] (col_name,...) reference_definition | check_constraint_definition } alter_option: { table_options | ADD [COLUMN] col_name column_definition [FIRST | AFTER col_name] | ADD [COLUMN] (col_name column_definition,...) | CHANGE [COLUMN] old_col_name new_col_name column_definition [FIRST | AFTER col_name] | MODIFY [COLUMN] col_name column_definition [FIRST | AFTER col_name] ...
其中column_definition为:
column_definition: { data_type [NOT NULL | NULL] [DEFAULT {literal | (expr)} ] [VISIBLE | INVISIBLE] [AUTO_INCREMENT] [UNIQUE [KEY]] [[PRIMARY] KEY] [COMMENT 'string'] [COLLATE collation_name] [COLUMN_FORMAT {FIXED | DYNAMIC | DEFAULT}] [COLUMN_FORMAT {FIXED|DYNAMIC|DEFAULT}|COMPRESSED[={ZLIB|ZSTD}**]] [ENGINE_ATTRIBUTE [=] 'string'] [SECONDARY_ENGINE_ATTRIBUTE [=] 'string'] [STORAGE {DISK | MEMORY}] [reference_definition] [check_constraint_definition] | data_type [COLLATE collation_name] [GENERATED ALWAYS] AS (expr) [VIRTUAL | STORED] [NOT NULL | NULL] [VISIBLE | INVISIBLE] [UNIQUE [KEY]] [[PRIMARY] KEY] [COMMENT 'string'] [reference_definition] [check_constraint_definition] }
特性参数说明
参数名称 |
描述 |
取值范围 |
默认值 |
级别 |
是否动态生效 |
---|---|---|---|---|---|
rds_column_compression |
|
[0,2] |
0 |
GLOBAL |
是 |
rds_default_column_compression_algorithm |
设置字段压缩特性默认的压缩算法,适用于如下场景:
|
ZLIB或ZSTD |
ZLIB |
GLOBAL |
是 |
rds_column_compression_threshold |
设置字段压缩特性的阈值。
|
[20-4294967295] |
100 |
GLOBAL |
是 |
rds_zlib_column_compression_level |
控制字段压缩特性中zlib压缩算法的压缩级别。
|
[0,9] |
6 |
GLOBAL |
是 |
rds_zstd_column_compression_level |
控制字段压缩特性中zstd压缩算法的压缩级别。 取值越小,压缩速度越快但压缩效果越差;取值越大,压缩速度越慢但压缩效果越好。 |
[1,22] |
3 |
GLOBAL |
是 |
使用示例
- 显式创建压缩字段。
mysql> show variables like 'rds_column_compression'; +------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | rds_column_compression | 1 | +------------------------+-------+ 1 row in set (0.00 sec) mysql> show variables like 'rds_default_column_compression_algorithm'; +------------------------------------------+-------+ | Variable_name | Value | +------------------------------------------+-------+ | rds_default_column_compression_algorithm | ZLIB | +------------------------------------------+-------+ 1 row in set (0.00 sec) mysql> create table t1(c1 varchar(100) compressed, c2 varchar(100) compressed=zlib, c3 varchar(100) compressed=zstd) default charset=latin1; Query OK, 0 rows affected (0.06 sec) mysql> show create table t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `c1` varchar(100) /*!99990 800220201 COMPRESSED=ZLIB */ DEFAULT NULL, `c2` varchar(100) /*!99990 800220201 COMPRESSED=ZLIB */ DEFAULT NULL, `c3` varchar(100) /*!99990 800220201 COMPRESSED=ZSTD */ DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.00 sec)
- 自动创建压缩字段。
mysql> set global rds_column_compression = 2; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'rds_column_compression'; +------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | rds_column_compression | 2 | +------------------------+-------+ 1 row in set (0.01 sec) mysql> show variables like 'rds_column_compression_threshold'; +----------------------------------+-------+ | Variable_name | Value | +----------------------------------+-------+ | rds_column_compression_threshold | 100 | +----------------------------------+-------+ 1 row in set (0.01 sec) mysql> show variables like 'rds_default_column_compression_algorithm'; +------------------------------------------+-------+ | Variable_name | Value | +------------------------------------------+-------+ | rds_default_column_compression_algorithm | ZLIB | +------------------------------------------+-------+ 1 row in set (0.01 sec) mysql> create table t2(c1 varchar(99), c2 varchar(100)) default charset=latin1; Query OK, 0 rows affected (0.05 sec) mysql> show create table t2\G *************************** 1. row *************************** Table: t2 Create Table: CREATE TABLE `t2` ( `c1` varchar(99) DEFAULT NULL, `c2` varchar(100) /*!99990 800220201 COMPRESSED=ZLIB */ DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.01 sec)
- 关闭特性。
mysql> set global rds_column_compression = 0; Query OK, 0 rows affected (0.00 sec) mysql> show variables like 'rds_column_compression'; +------------------------+-------+ | Variable_name | Value | +------------------------+-------+ | rds_column_compression | 0 | +------------------------+-------+ 1 row in set (0.01 sec) mysql> show variables like 'rds_column_compression_threshold'; +----------------------------------+-------+ | Variable_name | Value | +----------------------------------+-------+ | rds_column_compression_threshold | 100 | +----------------------------------+-------+ 1 row in set (0.01 sec) mysql> create table t3(c1 varchar(100) compressed, c2 varchar(100) compressed=zlib, c3 varchar(100) compressed=zstd) default charset=latin1; Query OK, 0 rows affected, 3 warnings (0.04 sec) mysql> show create table t3\G *************************** 1. row *************************** Table: t3 Create Table: CREATE TABLE `t3` ( `c1` varchar(100) DEFAULT NULL, `c2` varchar(100) DEFAULT NULL, `c3` varchar(100) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.01 sec)
确认效果
- 通过执行show create table语句展示表结构信息,发现其中包含/*!99990 800220201 COMPRESSED=xxxx */的内容,可认为已使用字段压缩特性。
mysql> show create table t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `c1` varchar(100) /*!99990 800220201 COMPRESSED=ZLIB */ DEFAULT NULL, `c2` varchar(100) /*!99990 800220201 COMPRESSED=ZLIB */ DEFAULT NULL, `c3` varchar(100) /*!99990 800220201 COMPRESSED=ZSTD */ DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.00 sec)
- 利用系统视图information_schema.columns查询压缩字段。
mysql> select TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, EXTRA from information_schema.columns where extra like '%compressed%'; +--------------+------------+-------------+-----------------+ | TABLE_SCHEMA | TABLE_NAME | COLUMN_NAME | EXTRA | +--------------+------------+-------------+-----------------+ | test | t1 | c1 | COMPRESSED=ZLIB | | test | t1 | c2 | COMPRESSED=ZLIB | | test | t1 | c3 | COMPRESSED=ZSTD | | test | t2 | c2 | COMPRESSED=ZLIB | +--------------+------------+-------------+-----------------+ 4 rows in set (0.50 sec)
- 通过查询status信息,以确认字段压缩或解压缩接口的实际调用次数。
mysql> show global status like '%column%compress%'; +--------------------------------+-------+ | Variable_name | Value | +--------------------------------+-------+ | Innodb_column_compress_count | 243 | | Innodb_column_uncompress_count | 34 | +--------------------------------+-------+
- 通过执行如下语句或者查看监控界面信息,对比压缩前后表占用大小,确认压缩效果。
SELECT table_name AS Table, round(((data_length + index_length) / 1024 / 1024), 2) AS Size in MB FROM information_schema.TABLES WHERE table_schema = "***" and table_name='***'
压缩比和性能影响验证
- 插入随机数据场景,表中有1万行数据,每行是由400个MD5函数返回的32位字符串构成。
CREATE TABLE `random_data` ( `id` int(11) NOT NULL AUTO_INCREMENT, `data` longtext, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; DELIMITER $$ CREATE PROCEDURE `generate_random_data`() BEGIN DECLARE i INT DEFAULT 1; DECLARE j INT DEFAULT 1; DECLARE str longtext; WHILE i <= 10000 DO SET j = 1; SET str = ''; WHILE j <= 400 DO SET str = CONCAT(str, MD5(RAND())); SET j = j + 1; END WHILE; INSERT INTO `random_data` (`data`) VALUES (str); SET i = i + 1; END WHILE; END$$ DELIMITER ;
分别设置rds_column_compression=0和rds_column_compression=2,其他参数默认,导入如上表结构并调用存储过程插入数据,利用zlib/ztsd算法压缩, 计算压缩前后数据文件大小的比率为1.8。
- 通过sysbench导入64张表,每张表1000万行数据,其中c和pad字段类型更改为varchar,修改后的表结构如下所示:
CREATE TABLE `sbtest1` ( `id` int NOT NULL AUTO_INCREMENT, `k` int NOT NULL DEFAULT '0', `c` varchar(120) COLLATE utf8mb4_0900_bin NOT NULL DEFAULT '', `pad` varchar(60) COLLATE utf8mb4_0900_bin NOT NULL DEFAULT '', PRIMARY KEY (`id`), KEY `k_1` (`k`) ) ENGINE=InnoDB AUTO_INCREMENT=10000001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_bin
- 分别设置rds_column_compression=0和rds_column_compression=2,其他参数默认,导入表结构和数据,计算收益后实际只对c列进行zlib/zstd压缩,计算压缩前后数据文件大小的比率为1.2。
- 性能测试方面,理论上压缩级别越高对性能的影响越大,压缩后性能损耗在10%左右。