当mysql表从压缩表变成普通表会发生什么
前言
本文章做了把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表从压缩表变成普通表会发生什么的更多相关文章
- 【转】MYISAM表批量压缩
关于对MYISAM表的压缩,可以使用myisampack和myisamchk完成(myisampack完之后必须进行myisamchk才能使用压缩后的表,而且是只读的), 其详细地用法可以参考官方文档 ...
- MySql数据库3【优化1】表的优化
一.表结构的优化 1.标准化 标准化是在数据库中组织数据的过程.其中包括,根据设计规则创建表并在这些表间建立关系:通过取消冗余度与不一致相关性,该设计规则可以同时保护数据并提高数据的灵活性.通常数据 ...
- Mysql系列五:数据库分库分表中间件mycat的安装和mycat配置详解
一.mycat的安装 环境准备:准备一台虚拟机192.168.152.128 1. 下载mycat cd /softwarewget http:-linux.tar.gz 2. 解压mycat tar ...
- mysql更新(三)语句 库的操作 表的操作
04-初始mysql语句 本节课先对mysql的基本语法初体验. 操作文件夹(库) 增 create database db1 charset utf8; 查 # 查看当前创建的数据库 show ...
- (转)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% ...
- mysql 库操作、存储引擎、表操作
阅读目录 库操作 存储引擎 什么是存储引擎 mysql支持的存储引擎 如何使用存储引擎 表操作 创建表 查看表结构 修改表ALTER TABLE 复制表 删除表 数据类型 表完整性约束 回到顶部 一. ...
- MySQL技术内幕InnoDB存储引擎(表&索引算法和锁)
表 4.1.innodb存储引擎表类型 innodb表类似oracle的IOT表(索引聚集表-indexorganized table),在innodb表中每张表都会有一个主键,如果在创建表时没有显示 ...
- 重新学习Mysql数据13:Mysql主从复制,读写分离,分表分库策略与实践
一.MySQL扩展具体的实现方式 随着业务规模的不断扩大,需要选择合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量. 关于数据库的扩展主要包括:业务拆分.主从复制.读写分离.数据库分库 ...
- mysql使用MRG_MyISAM(MERGE)实现水平分表
在MySQL中数据的优化尤其是大数据量的优化是一门很大的学问,当然其它数据库也是如此,即使你不是DBA,做为一名程序员掌握一些基本的优化信息,也可以让你在自己的程序开发中受益匪浅.当然数据库的优化有很 ...
随机推荐
- 【kubernetes 问题排查】使用 kubeadm 部署时遇到的问题
引言 再使用kubeadm部署集群时会多少遇到一些问题,这里做下记录,方便后面查找问题时有方向,同时也为刚要入坑的你指明下方向,让你少走点弯路 问题汇总 The connection to the s ...
- .NET桌面程序应用WebView2组件集成网页开发4 WebView2的线程模型
系列目录 [已更新最新开发文章,点击查看详细] WebView2控件基于组件对象模型(COM),必须在单线程单元(STA)线程上运行. 线程安全 WebView2必须在使用消息泵的UI线程上创 ...
- Git (常用命令)
某程序猿退休后决定练习书法,于是花重金买下文房四宝.某日,饭后突生雅兴,一番磨墨拟纸 并点上上好檀香.定神片刻,泼墨挥毫,郑重地写下一行:Hello World 斯~ 有被冷到吗哈哈哈 Git常用命令 ...
- CentOS 8配置本地yum源及DNF简介
CentOS 8更改了软件包的安装程序,取消了 yum 的配置方法,改而使用了dnf 作为安装程序.虽然改变了软件包的安装方式,但是 dnf 还是能兼容使用 yum 的配置文件和命令的使用方法. 小提 ...
- 『现学现忘』Git基础 — 22、Git中文件重命名
目录 1.用学过的命令进行文件重命名 2.使用git mv命令进行文件重命名 我们这篇文章来说说在Git中如何进行文件重命名. 提示一下,下面所说明的是对已经被Git管理的文件进行重命名,未被Git追 ...
- MySQL8新增降序索引
MySQL8新增降序索引 桃花坞里桃花庵,桃花庵里桃花仙.桃花仙人种桃树,又摘桃花卖酒钱. 一.MySQL5.7 降序索引 MySQL在语法上很早就已经支持降序索引,但实际上创建的却仍然是升序索引,如 ...
- 更换国内镜像源进行pip安装
Linux中当我们需要安装某个模块时(比如tensorflow2.0.0),常见有三种方法: pip install tensorflow==2.0.0 pip install https://pyp ...
- NLP教程(7) - 问答系统
作者:韩信子@ShowMeAI 教程地址:http://www.showmeai.tech/tutorials/36 本文地址:http://www.showmeai.tech/article-det ...
- 渗透:Nmap
Nmap,也就是Network Mapper,最早是Linux下的网络扫描和嗅探工具包. nmap是一个网络连接端扫描软件,用来扫描网上电脑开放的网络连接端.确定哪些服务运行在哪些连接端,并且推断计算 ...
- Improved Security for a Ring-Based Fully Homomorphic Encryption Scheme-2013:解读
本文记录阅读此论文的笔记 摘要 (1)1996年,HPS三人提出一个格上的高效加密方案,叫做NTRUEncrypt,但是没有安全性证明:之后2011年,SS等人修改此方案,将其安全规约到标准格上的困难 ...