前言

本文章做了把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. python学习-Day29

    目录 今日内容详细 反射实际案例 面向对象的双下方法 __ str __ __ del __ __ getattr __ __ setattr __ __ call __ __ enter __ __ ...

  2. 攻防世界-MISC:掀桌子

    这是攻防世界新手练习区的第八题,题目如下: 就给了一串16进制的字符串.哎,又是不懂,看了一下官方WP,说是将每两位16进制数转换为10进制,再减去128再转换为ASCII码.直接上脚本 str1 = ...

  3. 使用WebDriverManager实现自动获取浏览器驱动程序

    原理: 自动到指定的地址下载相应的浏览器驱动保存到缓存区 ~/.cache/selenium 痛点: 解决因Chrome浏览器升级,driver需要同步升级,要重新下载驱动的问题 区别: 传统方式 需 ...

  4. 如何在 pyqt 中解决启用 DPI 缩放后 QIcon 模糊的问题

    问题描述 如今显示器的分辨率越来越高,如果不启用 DPI 缩放,软件的字体和图标在高分屏下就会显得非常小,看得很累人.从 5.6 版本开始,Qt 便能支持 DPI 缩放功能,Qt6 开始这个功能是默认 ...

  5. UDP协议,多道技术,进程,同步与异步,阻塞与非阻塞

    UDP协议 简介 UDP叫做用户数据报协议,是OSI七层参考模型中传输层使用的协议,他提供的是不可靠传输,既它在传输过程 中不保证数据的完整性! 端口号 UDP使用IP地址和端口号进行标识,以此将数据 ...

  6. GitHub 毕业年鉴「GitHub 热点速览 v.22.20」

    GitHub 毕业需要什么呢?一个 PR!那么提交一个 PR 需要什么?也许你是使用终端命令来提交 git 操作的,那么你可以了解下 Bash-Oneliner,收录了大量好用的 bash 命令,虽然 ...

  7. 739. Daily Temperatures - LeetCode

    Question 739. Daily Temperatures Solution 题目大意:比今天温度还要高还需要几天 思路:笨方法实现,每次遍历未来几天,比今天温度高,就坐标减 Java实现: p ...

  8. 向sqlserver 数据库插入emoji 表情包

    1.emoji 属于特殊字符 所以我们必须使用utf-8 的编码格式进行保存  不过好在sqlserver 默认支持utf-8 2.将需要存储emoji的字段必须设置为nvarchar 类型  因为v ...

  9. 关于『Markdown』:第二弹

    关于『Markdown』:第二弹 建议缩放90%食用 道家有云:一生二,二生三,三生万物 为什么我的帖子不是这样 各位打工人们! 自从我学了Markdown以来 发现 Markdown 语法真的要比 ...

  10. cloudwu/coroutine 源码分析

    1 与其它协程库使用对比 这个 C 协程库是云风(cloudwu) 写的,其接口风格与 Lua 协程类似,并且都是非对称 stackful 协程.这个是源代码中的示例: #include " ...