前言

本文章做了把mysql表从压缩表过渡到普通表的实验过程,看看压缩表变成普通表会发生什么?本文针对mysql5.7和mysql8分别进行了实验。

1、什么是表压缩

在介绍压缩表变成普通表前,首先给大家普及下,什么是表压缩。

表压缩,意思是使表中的数据以压缩格式存储,压缩能够显著提高处理速度和压缩磁盘 。压缩意味着在硬盘和内存之间传输的数据更小且占用相对少的内存及硬盘,对于辅助索引,这种压缩带来更加明显的好处,因为索引数据也被压缩了。

表压缩是有很大好处的,能减少磁盘的I/O,还能提高系统吞吐量,节约空间,压缩率越大,占用的磁盘空间越小,文件传输时间提升,降低数据的存储和网络传输成本。

2、如何表压缩( mysql的版本需要大于5.5 )

1、首先设置my.inf参数

#打开配置文件
vim /etc/my.inf #加入配置项
innodb_file_per_table=1
innodb_file_format=Barracuda
innodb_strict_mode=1 #建议加上
innodb_default_row_format = COMPRESSED #在整个库默认启用行压缩格式时设定,一边不改变此值 #重启数据库
systemctl restart mysqld

2、对表压缩

mysql> alter table t1 ROW_FORMAT=COMPRESSED;

3、压缩表转换为普通表

mysql> alter table t1 ROW_FORMAT=DEFAULT;

针对mysql5.7开始实验

  • mysql数据库版本:5.7.31

  • linux版本:centos5.7

1、建表和初始化测试数据


#1、建表
CREATE TABLE test_compress (
   id bigint(20) unsigned NOT NULL,
   identification_id int(10) unsigned DEFAULT NULL,
   timestamp datetime NOT NULL,
   action varchar(50) NOT NULL,
   result varchar(50) NOT NULL,
   PRIMARY KEY (id),
   KEY INDEX_test_compress_result (result),
   KEY INDEX_test_compress_timestamp (timestamp)
   ) ENGINE=InnoDB DEFAULT CHARSET=latin1; #2、插入测试数据(linux里执行脚本)
for NUM in {1..100000}; do mysql -h localhost PS_57 -e "insert into test_compress (id, identification_id, timestamp, action, result) values ($NUM,$NUM*100,now(),concat('string',$NUM),concat('VeryVeryLargeString',$NUM))"; done

2、验证表的大小

让我们验证表的大小(之前执行innodb_stats_persistent_sample_pages=100000 的 ANALYZE 表,以便统计信息尽可能真实)。

set global innodb_stats_persistent_sample_pages=100000;
analyze table test_compress; +------------------------+---------+----------+----------+
| Table                  | Op      | Msg_type | Msg_text |
+------------------------+---------+----------+----------+
| PS_57.test_compress    | analyze | status   | OK       |
+------------------------+---------+----------+----------+
Query OK, 0 rows affected (0.00 sec)
select table_schema, table_name, table_rows,  round(data_length / 1024 / 1024)+round(index_length / 1024 / 1024)+round(data_free / 1024 / 1024) TOTAL_MB, create_options from information_schema.tables where table_name='test_compress';

+--------------+---------------+------------+----------+----------------+
| table_schema | table_name    | table_rows | TOTAL_MB | create_options |
+--------------+---------------+------------+----------+----------------+
| PS_57        | test_compress |     100000 |       37 |                |
+--------------+---------------+------------+----------+----------------+

3、对表压缩

接下来,我们将用KEY_BLOCK_SIZE=4压缩表(这个大小是任意选择的,在任何时候都没有指示或决定它是否是最优值,事实上,它不是)。

ALTER TABLE test_compress ROW_FORMAT=COMPRESSED,KEY_BLOCK_SIZE=4,ALGORITHM=INPLACE,LOCK=NONE;

Query OK, 0 rows affected (3.33 sec)

我们再次验证表的大小(以前执行innodb_stats_persistent_sample_pages=100000 的 ANALYZE 表,以便统计信息尽可能真实)。

set global innodb_stats_persistent_sample_pages=100000;

Query OK, 0 rows affected (0.00 sec)
analyze table test_compress;

+------------------------+---------+----------+----------+
| Table                  | Op      | Msg_type | Msg_text |
+------------------------+---------+----------+----------+
| PS_57.test_compress    | analyze | status   | OK       |
+------------------------+---------+----------+----------+
Query OK, 0 rows affected (0.00 sec)
select table_schema, table_name, table_rows,  round(data_length / 1024 / 1024)+round(index_length / 1024 / 1024)+round(data_free / 1024 / 1024) TOTAL_MB, create_options from information_schema.tables where table_name='test_compress';

+--------------+---------------+------------+----------+----------------------------------------+
| table_schema | table_name    | table_rows | TOTAL_MB | create_options                         |
+--------------+---------------+------------+----------+----------------------------------------+
| PS_57        | test_compress |     100000 |       19 | row_format=COMPRESSED KEY_BLOCK_SIZE=4 |
+--------------+---------------+------------+----------+----------------------------------------+

该表已被压缩,让我们检查其结构。

show create table test_compress;
*************************** 1. row ***************************
      Table: test_compress
Create Table: CREATE TABLE `test_compress` (
 `id` bigint(20) unsigned NOT NULL,
 `identification_id` int(10) unsigned DEFAULT NULL,
 `timestamp` datetime NOT NULL,
 `action` varchar(50) NOT NULL,
 `result` varchar(50) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `INDEX_test_compress_result` (`result`),
 KEY `INDEX_test_compress_timestamp` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4 1 row in set (0.00 sec)

4、压缩表解压缩(变成普通表)

ALTER TABLE test_compress ROW_FORMAT=DEFAULT,ALGORITHM=INPLACE,LOCK=NONE;

Query OK, 0 rows affected (6.25 sec)
Records: 0  Duplicates: 0  Warnings: 0

解压缩成功,让我们检查看看。

select table_schema, table_name, table_rows,  round(data_length / 1024 / 1024)+round(index_length / 1024 / 1024)+round(data_free / 1024 / 1024) TOTAL_MB, create_options from information_schema.tables where table_name='test_compress';

+--------------+---------------+------------+----------+--------------------+
| table_schema | table_name    | table_rows | TOTAL_MB | create_options     |
+--------------+---------------+------------+----------+--------------------+
| PS_57        | test_compress |     100000 |       25 | KEY_BLOCK_SIZE=4   |
+--------------+---------------+------------+----------+--------------------+

更好的检查:

show create table test_compress;

*************************** 1. row ***************************
      Table: test_compress
Create Table: CREATE TABLE `test_compress` (
 `id` bigint(20) unsigned NOT NULL,
 `identification_id` int(10) unsigned DEFAULT NULL,
 `timestamp` datetime NOT NULL,
 `action` varchar(50) NOT NULL,
 `result` varchar(50) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `INDEX_test_compress_result` (`result`),
 KEY `INDEX_test_compress_timestamp` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=4

出了点问题!KEY_BLOCK_SIZE仍然是4。

第二次尝试:

ALTER TABLE test_compress ROW_FORMAT=DEFAULT,KEY_BLOCK_SIZE=0,ALGORITHM=INPLACE,LOCK=NONE;

Query OK, 0 rows affected (2.05 sec)
Records: 0  Duplicates: 0  Warnings: 0
select table_schema, table_name, table_rows,  round(data_length / 1024 / 1024)+round(index_length / 1024 / 1024)+round(data_free / 1024 / 1024) TOTAL_MB, create_options from information_schema.tables where table_name='test_compress';
+--------------+---------------+------------+----------+--------------------+
| table_schema | table_name    | table_rows | TOTAL_MB | create_options     |
+--------------+---------------+------------+----------+--------------------+
| PS_57        | test_compress |     100000 |       25 |                    |
+--------------+---------------+------------+----------+--------------------+

更好的检查:

show create table test_compress\G
*************************** 1. row ***************************
      Table: test_compress
Create Table: CREATE TABLE `test_compress` (
 `id` bigint(20) unsigned NOT NULL,
 `identification_id` int(10) unsigned DEFAULT NULL,
 `timestamp` datetime NOT NULL,
 `action` varchar(50) NOT NULL,
 `result` varchar(50) NOT NULL,
 PRIMARY KEY (`id`) KEY_BLOCK_SIZE=4,
 KEY `INDEX_test_compress_result` (`result`) KEY_BLOCK_SIZE=4,
 KEY `INDEX_test_compress_timestamp` (`timestamp`) KEY_BLOCK_SIZE=4
) ENGINE=InnoDB DEFAULT CHARSET=latin1

出了点问题!主键和二级索引都继续显示 KEY_BLOCK_SIZE=4。

尽管当表从压缩转换为未压缩时,在内部,索引的KEY_BLOCK_SIZE支持表的索引,但 CREATE TABLE 语句则不然。起初,这将是一个美学/外观问题,但是当您进行转储时,这是一个真正的问题,因为CREATE TABLE保留了KEY_BLOCK_SIZE值,这并不好。以下是 mysqldump 的输出:

mysqldump -h localhost PS_57 test_compress --no-data > test_compress.sql
cat test_compress.sql
...
--
-- Table structure for table `test_compress`
-- DROP TABLE IF EXISTS `test_compress`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `test_compress` (
 `id` bigint(20) unsigned NOT NULL,
 `identification_id` int(10) unsigned DEFAULT NULL,
 `timestamp` datetime NOT NULL,
 `action` varchar(50) NOT NULL,
 `result` varchar(50) NOT NULL,
 PRIMARY KEY (`id`) KEY_BLOCK_SIZE=4,
 KEY `INDEX_test_compress_result` (`result`) KEY_BLOCK_SIZE=4,
 KEY `INDEX_test_compress_timestamp` (`timestamp`) KEY_BLOCK_SIZE=4
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

如您所见,似乎没有办法使用全局 ALTER TABLE 命令(如果可以这样称呼它)在表定义索引方面反转KEY_BLOCK_SIZE,因此我们将进行最后一次尝试:

ALTER TABLE test_compress
DROP PRIMARY KEY, add PRIMARY KEY (id),
DROP key INDEX_test_compress_result, add key INDEX_test_compress_result (result),
DROP key INDEX_test_compress_timestamp, add key INDEX_test_compress_timestamp (timestamp),
ROW_FORMAT=DEFAULT,KEY_BLOCK_SIZE=0,ALGORITHM=INPLACE,LOCK=NONE;

现在,它具有正确的定义,没有KEY_BLOCK_SIZE:

show create table test_compress;
*************************** 1. row ***************************
Table: test_compress
Create Table: CREATE TABLE `test_compress` (
`id` bigint(20) unsigned NOT NULL,
`identification_id` int(10) unsigned DEFAULT NULL,
`timestamp` datetime NOT NULL,
`action` varchar(50) NOT NULL,
`result` varchar(50) NOT NULL,
PRIMARY KEY (`id`),
KEY `INDEX_test_compress_result` (`result`),
KEY `INDEX_test_compress_timestamp` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
select table_schema, table_name, table_rows,  round(data_length / 1024 / 1024)+round(index_length / 1024 / 1024)+round(data_free / 1024 / 1024) TOTAL_MB, create_options from information_schema.tables where table_name='test_compress';
+--------------+---------------+------------+----------+----------------+
| table_schema | table_name    | table_rows | TOTAL_MB | create_options |
+--------------+---------------+------------+----------+----------------+
| PS_57        | test_compress |     100000 |       25 |                |
+--------------+---------------+------------+----------+----------------+

5、针对第4步出现问题的bug

mysql里有解释这个bug: https://bugs.mysql.com/bug.php?id=56628

针对mysql8实验

在MySQL 8中,情况如下:

select table_schema, table_name, table_rows,  round(data_length / 1024 / 1024)+round(index_length / 1024 / 1024)+round(data_free / 1024 / 1024) TOTAL_MB, create_options from information_schema.tables where table_name='test_compress';

+--------------+---------------+------------+----------+----------------+
| TABLE_SCHEMA | TABLE_NAME    | TABLE_ROWS | TOTAL_MB | CREATE_OPTIONS |
+--------------+---------------+------------+----------+----------------+
| PS_8         | test_compress |      31000 |       15 |                |
+--------------+---------------+------------+----------+----------------+

让我们执行 ALTER 来压缩表:

alter table test_compress ROW_FORMAT=COMPRESSED,KEY_BLOCK_SIZE=4,ALGORITHM=INPLACE,LOCK=NONE;

Query OK, 0 rows affected (4.54 sec)
Records: 0  Duplicates: 0  Warnings: 0

让我们再检查一下:

analyze table test_compress;

+-----------------------+---------+----------+----------+
| Table                 | Op      | Msg_type | Msg_text |
+-----------------------+---------+----------+----------+
| PS_8.test_compress    | analyze | status   | OK       |
+-----------------------+---------+----------+----------+
1 row in set (0.07 sec)
select table_schema, table_name, table_rows,  round(data_length / 1024 / 1024)+round(index_length / 1024 / 1024)+round(data_free / 1024 / 1024) TOTAL_MB, create_options from information_schema.tables where table_name='test_compress';

+--------------+---------------+------------+----------+----------------------------------------+
| TABLE_SCHEMA | TABLE_NAME    | TABLE_ROWS | TOTAL_MB | CREATE_OPTIONS                         |
+--------------+---------------+------------+----------+----------------------------------------+
| PS_8         | test_compress |     100000 |       19 | row_format=COMPRESSED KEY_BLOCK_SIZE=4 |
+--------------+---------------+------------+----------+----------------------------------------+
show create table test_compress;
*************************** 1. row ***************************
      Table: test_compress
Create Table: CREATE TABLE `test_compress` (
 `id` bigint unsigned NOT NULL,
 `identification_id` int unsigned DEFAULT NULL,
 `timestamp` datetime NOT NULL,
 `action` varchar(50) NOT NULL,
 `result` varchar(50) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `INDEX_test_compress_result` (`result`),
 KEY `INDEX_test_compress_timestamp` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4
1 row in set (0.01 sec)

到目前为止,一切都与MySQL 5.7相同:KEY_BLOCK_SIZE保留在整个表的定义中,而不是索引的定义中。

同样的,也能通过下面sql对表进行解压缩:

alter table test_compress ROW_FORMAT=DEFAULT, KEY_BLOCK_SIZE=0,ALGORITHM=INPLACE,LOCK=NONE;

Query OK, 0 rows affected (2.56 sec)
Records: 0  Duplicates: 0  Warnings: 0

查看解压缩情况

show create table test_compress;

*************************** 1. row ***************************
      Table: test_compress
Create Table: CREATE TABLE `test_compress` (
 `id` bigint unsigned NOT NULL,
 `identification_id` int unsigned DEFAULT NULL,
 `timestamp` datetime NOT NULL,
 `action` varchar(50) NOT NULL,
 `result` varchar(50) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `INDEX_test_compress_result` (`result`),
 KEY `INDEX_test_compress_timestamp` (`timestamp`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
select table_schema, table_name, table_rows,  round(data_length / 1024 / 1024)+round(index_length / 1024 / 1024)+round(data_free / 1024 / 1024) TOTAL_MB, create_options from information_schema.tables where table_name='test_compress';

+--------------+---------------+------------+----------+----------------+
| TABLE_SCHEMA | TABLE_NAME    | TABLE_ROWS | TOTAL_MB | CREATE_OPTIONS |
+--------------+---------------+------------+----------+----------------+
| PS_8         | test_compress |     100000 |       25 |                |
+--------------+---------------+------------+----------+----------------+

结论

在MySQL 5.7中,完全解压缩一张压缩表的唯一方法(至少在表及其索引的定义中)是重新生成主键及其所有索引。否则, 主键和二级索引都继续显示压缩表时候的KEY_BLOCK_SIZE。

然后在MySQL8里,修复了这个问题在MySQL5.7出现的问题。

当mysql表从压缩表变成普通表会发生什么的更多相关文章

  1. 【转】MYISAM表批量压缩

    关于对MYISAM表的压缩,可以使用myisampack和myisamchk完成(myisampack完之后必须进行myisamchk才能使用压缩后的表,而且是只读的), 其详细地用法可以参考官方文档 ...

  2. MySql数据库3【优化1】表的优化

    一.表结构的优化 1.标准化  标准化是在数据库中组织数据的过程.其中包括,根据设计规则创建表并在这些表间建立关系:通过取消冗余度与不一致相关性,该设计规则可以同时保护数据并提高数据的灵活性.通常数据 ...

  3. Mysql系列五:数据库分库分表中间件mycat的安装和mycat配置详解

    一.mycat的安装 环境准备:准备一台虚拟机192.168.152.128 1. 下载mycat cd /softwarewget http:-linux.tar.gz 2. 解压mycat tar ...

  4. mysql更新(三)语句 库的操作 表的操作

    04-初始mysql语句   本节课先对mysql的基本语法初体验. 操作文件夹(库) 增 create database db1 charset utf8; 查 # 查看当前创建的数据库 show ...

  5. (转)Mysql技术内幕InnoDB存储引擎-表&索引算法和锁

    表 原文:http://yingminxing.com/mysql%E6%8A%80%E6%9C%AF%E5%86%85%E5%B9%95innodb%E5%AD%98%E5%82%A8%E5%BC% ...

  6. mysql 库操作、存储引擎、表操作

    阅读目录 库操作 存储引擎 什么是存储引擎 mysql支持的存储引擎 如何使用存储引擎 表操作 创建表 查看表结构 修改表ALTER TABLE 复制表 删除表 数据类型 表完整性约束 回到顶部 一. ...

  7. MySQL技术内幕InnoDB存储引擎(表&索引算法和锁)

    表 4.1.innodb存储引擎表类型 innodb表类似oracle的IOT表(索引聚集表-indexorganized table),在innodb表中每张表都会有一个主键,如果在创建表时没有显示 ...

  8. 重新学习Mysql数据13:Mysql主从复制,读写分离,分表分库策略与实践

    一.MySQL扩展具体的实现方式 随着业务规模的不断扩大,需要选择合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量. 关于数据库的扩展主要包括:业务拆分.主从复制.读写分离.数据库分库 ...

  9. mysql使用MRG_MyISAM(MERGE)实现水平分表

    在MySQL中数据的优化尤其是大数据量的优化是一门很大的学问,当然其它数据库也是如此,即使你不是DBA,做为一名程序员掌握一些基本的优化信息,也可以让你在自己的程序开发中受益匪浅.当然数据库的优化有很 ...

随机推荐

  1. [AcWing 771] 字符串中最长的连续出现的字符

    点击查看代码 #include<iostream> using namespace std; string str; int n; int main() { cin >> n; ...

  2. [题解][YZOJ50104] 密码 | 简单计数

    同步发表于 Mina! 题目大意 对于满足以下要求的长度为 \(n\) 的序列进行计数: 序列的值域为 \([1,k]\); 对于序列的任意位置 \(p\in[1,n]\),可以找到至少一个 \(i\ ...

  3. 面试官:Kafka是什么,它有什么特性与使用场景?

    哈喽!大家好,我是小奇,一位热爱分享的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 不知不觉进入了五月份了,天气越 ...

  4. 国内访问 git 慢的方法

    在国内访问 git 的时候,总会存在访问慢或者git clone 的时候报下面的错误 这个时候,我们可以使用代理的方式去进行访问 需要注意的是:你必须存在一个国外的,能够让你快速访问到 GitHub ...

  5. 重新认识 MSBuild - 1

    前言 很多人一谈到 MSBuild,脑子里就会出现 "XML"."只能用 VS 的属性框图形界面操作"."可定制性和扩展性差" 和 &quo ...

  6. arts-week13

    Algorithm 992. Sort Array By Parity II - LeetCode Review https://tls.ulfheim.net/ HTTP协议图解 Tip linux ...

  7. Fail2ban 命令详解 fail2ban-client

    Fail2ban的客户端操作命令,用于控制服务端. root@ubuntu:~# fail2ban-client --help Usage: /usr/bin/fail2ban-client [OPT ...

  8. 学习Linux须知1.0之Linux相关概念、工具(yum、vim)、防火墙等

    温馨提示:重点掌握的前面都标注了 ☆ 一.Linux 是什么? Linux 是一个操作系统. 我们的 Linux 主要是系统调用和内核那两层. 当然直观地看,我们使用的操作系统还包含一些在其上运行的应 ...

  9. 如何让 Windows 把 TypeScript 文件当作文本文件

    TL;DR 修改注册表项 HKEY_CLASSES_ROOT\.ts 为 HKEY_CLASSES_ROOT\.txt 的值 起因 Windows10 总把 TypeScript 文件自动当成视频,放 ...

  10. 【Unity Shader学习笔记】Unity光照基础-高光反射

    1.原理 1.1.Phong模型 计算高光反射需要表面法线.视角方向.光源方向.反射方向等. 在这四个矢量中,我们实际上只需要知道其中3个矢量即可,而第4个矢量(反射方向r)可以通过其他信息计算得到: ...