更新时间:2024-12-23 GMT+08:00

字段压缩

为了减少数据页面存储空间占用,节省成本,TaurusDB推出细粒度的字段压缩,提供ZLIB和ZSTD两种压缩算法,用户可以综合考虑压缩比和压缩解压性能影响,选择合适的压缩算法,对不频繁访问的大字段进行压缩。同时,字段压缩特性提供自动压缩的能力,帮助用户更方便地使用此特性。

使用场景:降本,表中包含不频繁访问的大字段。

使用须知

  • TaurusDB实例内核版本大于等于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]
}

特性参数说明

表1 参数说明

参数名称

描述

取值范围

默认值

级别

是否动态生效

rds_column_compression

  • 当参数取值为0时,表示字段压缩特性关闭,不再支持显式或者自动创建压缩列。
  • 当参数取值为1时,表示仅支持显式创建压缩列。
  • 当参数取值为2时,表示同时支持显式或自动创建压缩列。

[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时代表不压缩。
  • 取值为除0外范围内的其他参数值时,取值越小,压缩速度越快但压缩效果越差;取值越大,压缩速度越慢但压缩效果越好。

[0,9]

6

GLOBAL

rds_zstd_column_compression_level

控制字段压缩特性中zstd压缩算法的压缩级别。

取值越小,压缩速度越快但压缩效果越差;取值越大,压缩速度越慢但压缩效果越好。

[1,22]

3

GLOBAL

使用示例

  1. 显式创建压缩字段。
    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)
  2. 自动创建压缩字段。
    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)
  3. 关闭特性。
    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)

确认效果

  1. 通过执行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)
  2. 利用系统视图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)
  3. 通过查询status信息,以确认字段压缩或解压缩接口的实际调用次数。
    mysql> show global status like '%column%compress%';
    +--------------------------------+-------+
    | Variable_name                  | Value |
    +--------------------------------+-------+
    | Innodb_column_compress_count   | 243   |
    | Innodb_column_uncompress_count | 34    |
    +--------------------------------+-------+
  4. 通过执行如下语句或者查看监控界面信息,对比压缩前后表占用大小,确认压缩效果。
    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. 插入随机数据场景,表中有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。

  2. 通过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%左右。