当mysql表从压缩表变成普通表会发生什么

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

1、什么是表压缩

在将压缩表引入普通表之前,让我们首先普及表压缩是什么。

[En]

Before introducing compressed tables to ordinary tables, let’s first popularize what table compression is.

表压缩,即表中的数据是以压缩格式存储的,压缩可以显著提高处理速度,压缩磁盘。压缩意味着硬盘和内存之间传输的数据更少,占用的内存和硬盘相对更少,这种压缩给二级索引带来的好处更明显,因为索引数据也是压缩的。

[En]

Table compression, which means that the data in the table is stored in a compressed format, compression can significantly improve processing speed and compress the disk. Compression means that less data is transferred between the hard disk and memory and takes up relatively less memory and the hard disk, and this compression brings more obvious benefits to secondary indexes because the index data is also compressed.

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

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

#打开配置文件
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
mysql> alter table t1 ROW_FORMAT=COMPRESSED;
mysql> alter table t1 ROW_FORMAT=DEFAULT;
  • 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 |
+--------------+---------------+------------+----------+----------------------------------------+

这张桌子已经被压缩了,让我们检查一下它的结构。

[En]

The table has been compressed, let’s check its structure.

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

拉链解压成功,让我们来检查一下。

[En]

Unzipped successfully, let’s check it.

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 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 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出现的问题。

更多资讯,敬请关注微信公众号[程序员],分享优质文章,编程酷科技,帮你成为程序员!

[En]

For more information, please follow the Wechat official account [programmer], share high-quality articles, programming cool techs, to help you become a programmer!

Original: https://www.cnblogs.com/zhbeier/p/16470091.html
Author: 奇想派
Title: 当mysql表从压缩表变成普通表会发生什么

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/505242/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • API开放平台网关需要做什么?

    首发于公众号:BiggerBoy欢迎关注,查看更多技术文章 怎么搭建API开放平台网关? API的全称是应用编程接口(Application Programming Interfa…

    数据库 2023年6月11日
    0135
  • java中如何在ISO-8859-1和UTF-8之间相互转换呢?

    我们都知道在一些特殊的场景,我们需采用特殊的编码格式,如:UTF-8,但是系统默认的编码为ISO-8859-1 那么我们就需要将编码转换为我们所需的编码格式, 今天我就遇到这个问题…

    数据库 2023年6月11日
    0130
  • Vue 2.0 基础

    知识点 1.是一个MVVM框架 由MVC架构衍生,分为View(视图层)、ViewModel(数据视图层)、Model(数据层),MVVM 最标志性的特性就是 数据绑定,实现数据驱…

    数据库 2023年6月11日
    0137
  • HyperLogLog

    HyperLogLog 基数计数,不绝对准确。省空间,速度快 估计基数,对数级空间节省 可以理解为一种压缩,把基数压缩成二进制位数,只存储位数,如果旧有的数据再加入时肯定不会改变位…

    数据库 2023年6月9日
    0108
  • JWT+SpringSecurity登录和权限管理

    一、什么是JWT 说起JWT,我们应该来谈一谈基于token的认证和传统的session认证的区别。说起JWT,我们应该来谈一谈基于token的认证和传统的session认证的区别…

    数据库 2023年6月6日
    0125
  • python-图片文字识别

    两种方法 1. 第一种方法 from PIL import Image import pytesseract import re #导入…

    数据库 2023年6月14日
    0119
  • [LeetCode]1464. 数组中两元素的最大乘积

    给你一个整数数组 nums,请你选择数组的两个不同下标 i 和 j,使 (nums[i]-1)*(nums[j]-1) 取得最大值。 请你计算并返回该式的最大值。 示例 1: 输入…

    数据库 2023年6月9日
    0128
  • MySQL max() min() 函数取值错误

    今天日志出现异常,一步一步debug发现SQL语句返回值出错,进一步发现是max()函数返回出错。点击跳转解决办法,赶时间的朋友可以去获得答案。当然我还是希望大伙看看原由。 sel…

    数据库 2023年5月24日
    0119
  • MySQL实现阶段累加的sql写法 ,eq:统计余额

    最近项目碰到一个新的需求,统计每日充值/消费之后的余额。对于这种需求,其实也很简单,只需要在每次充值/消费后,计算下余额,然后保存下来就可以了。但是对于这种需求,一条sql就能搞定…

    数据库 2023年6月16日
    0123
  • Tomcat8下的Redis会话共享

    前言: 最近在做网站的升级,从 Tomcat7升级到 Tomcat8版本,因为没接触过,就以为升级下Tomcat的版本就万事大吉,可是天不如人愿,很顺利的将应用升级到了Tomcat…

    数据库 2023年6月14日
    0140
  • 高可用 | 关于 Xenon 高可用的一些思考

    原创:知数堂 Xenon 不会补日志,Xenon 只会从包含最大 GTID 的所有 Follower 中选举一个 Follower,使之成为 Leader 。重新配置主从复制,并把…

    数据库 2023年5月24日
    0116
  • Vue(十一)—key特殊attribute

    预期: number | string | boolean (2.4.2 新增) | symbol (2.5.12 &#x65B…

    数据库 2023年6月16日
    0134
  • 手把手教你定位线上MySQL慢查询问题,包教包会

    1. 慢查询日志的作用 默认情况下不启用慢速日志。建议手动启用,以便我们更轻松地定位在线问题。 [En] Slow log is not enabled by default. I…

    数据库 2023年5月24日
    0138
  • LIMIT和OFFSET分页性能差!今天来介绍如何高性能分页

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。 GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。 前言 之前的大多数人分页采用的都…

    数据库 2023年6月11日
    0163
  • 开发思想

    解决的问题:一类对象,不同对象有不同的处理 顶级接口 定义规范,面向接口编程 抽象策略 定义一套模板,不同的交给不同的策略实现 具体策略 枚举 对象标识 –具体策略 策…

    数据库 2023年6月11日
    0114
  • 前端JavaScript-每日一题

    2022 09 本文来自博客园,作者:吴知木,转载请注明原文链接:https://www.cnblogs.com/zh1q1/p/16726853.html Original: h…

    数据库 2023年6月11日
    0117
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球