當mysql表從壓縮表變成普通表會發生什麼

来源:https://www.cnblogs.com/zhbeier/archive/2022/07/12/16470091.html
-Advertisement-
Play Games

前言 本文章做了把mysql表從壓縮表過渡到普通表的實驗過程,看看壓縮表變成普通表會發生什麼?本文針對mysql5.7和mysql8分別進行了實驗。 1、什麼是表壓縮 在介紹壓縮表變成普通表前,首先給大家普及下,什麼是表壓縮。 表壓縮,意思是使表中的數據以壓縮格式存儲,壓縮能夠顯著提高處理速度和壓縮 ...


前言

本文章做了把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出現的問題。

更多內容請關註微信公眾號【編程達人】,分享優質好文章,編程黑科技,助你成為編程達人!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一 Linux操作系統和Shell 簡介 操作系統(Operating Systems, OS)實際上是一種用於電腦的軟、硬體資源管理調度的系統級軟體,它的主體是內核(Kernel),其主要負責進程管理、記憶體管理、文件管理和外設管理等功能,而它也向外界提供了內核的介面即系統調用(System Ca ...
  • 讀了 @SnailMann大佬【MySQL筆記】正確的理解MySQL的MVCC及實現原理 收益頗豐,非常感謝! 但對其中如何判斷事務是否可見性還是不太理解,於是作了本文,在原博客基礎上,舉例畫圖論證、理解了**Read View**的可見性判斷。 引用 @SnailMann大佬【MySQL筆記】正確 ...
  • redis 憑藉著強大的功能和可靠的穩定性,應用場景越來越廣。逐漸成為軟體開發工程師必備的技能之一。 本篇文章,暫不做基本功能的介紹。直接教大家如何部署redis集群。 集群演進主要分為2部分。 ##一、主從備份機制 一個redis 主服務可以擁有多個從服務;一個從伺服器,只可擁有一個主服務。從服務 ...
  • ClickHouse集群的搭建和部署和單機的部署是類似的,主要在於配置的不一致,如果需要瞭解ClickHouse單機的安裝設部署,可以看看這篇文章,ClickHouse(03)ClickHouse怎麼安裝和部署。 ClickHouse集群部署流程大概如下: 環境準備 在每台機器上安裝單機版Click ...
  • MySQL 高級 1、約束 1.1、約束介紹 什麼是約束 對錶中的數據進行限定,保證數據的正確性、有效性、完整性 約束類型 | 約束 | 說明 | | : : | : : | | PRIMARY KEY | 主鍵約束 | | UNIQUE | 唯一約束 | | NOT NULL | 非空約束 | | ...
  • 原文鏈接:批流一體數據集成工具ChunJun同步Hive事務表原理詳解及實戰分享 課件獲取:關註公眾號__ “數棧研習社”,後臺私信 “ChengYing”__ 獲得直播課件 視頻回放:點擊這裡 ChengYing 開源項目地址:github 丨 gitee 喜歡我們的項目給我們點個__ STAR! ...
  • dolphinscheduler單機化改造 轉載請註明出處: https://www.cnblogs.com/funnyzpc/p/16466920.html 前面 其實如果單機的話直接走standalone-server就可以了,簡單又快捷,如果更改的話 後期要升級可能又需要維護個版本才可,所以簡 ...
  • SQL Server 中的事務是什麼? 事務是應該作為一個單元執行的一組 SQL 語句。這意味著事務確保所有命令都成功或都不成功。如果事務中的命令之一失敗,則所有命令都失敗,並且在資料庫中修改的任何數據都將回滾。 比如您在做一個銀行轉賬操作,這涉及了2個操作, 扣款和收款, 必須保證這2個操作都成功 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...