MySQL中的表壓縮功能

MySQL版本:8.0.22

os:linux ubuntu

語言:c++、c

在MySQL中支持3種類型的表壓縮,依次爲:傳統壓縮、TPC壓縮、字典壓縮。

第一種:傳統壓縮

傳統的表壓縮方式是在MySQL5.0.7之前使用的,現在已經廢棄了,因爲這種方式不但沒有提升數據庫的效率,反而降低了效率,導致buffer pool的使用率降低了。

create table時指定壓縮後表的大小,即 KEY_BLOCK_SIZE 的大小,page默認大小爲16KB。壓縮是按page爲單位進行壓縮的。

SQL語句:

create table tt 
(
    c1 int primary key,
    c2 varchar(50)
) engine = innodb KEY_BLOCK_SIZE=8; 
 
KEY_BLOCK_SIZE 的取值爲: 1,2,4,8,16
表示一個16KB的page壓縮之後是8KB。如果一個page壓縮之後的大小爲9KB,那麼需要2個8KB的page進行存儲。如果一個page壓縮之後的大小爲6KB,那麼只需要1個8KB的page進行存儲即可。

KEY_BLOCK_SIZE的大小可以是 1、2、4、8、16,表示啓用頁壓縮,然後按照 1K、2K、4K、8K、16K 的頁大小存儲數據。如果設置KEY_BLOCK_SIZE的大小爲0,那麼MySQL自動的將KEY_BLOCK_SIZE設置爲innodb_page_size/2;

缺點:一個頁在緩衝池中存在兩個版本,壓縮前的原始版本和壓縮後的版本,這樣導致緩衝池中能緩存page頁的數量大大減少,在buffer pool中多產生一個page。對於一個16KB的page,一個存放的是原來的16KB的頁數據,另一個是壓縮後的page,壓縮後以8KB爲例,8KB中存放的是壓縮後的數據再加上redo.log日誌以及file header和file tailer部分。

因此,這種壓縮方式會額外的多佔用一個page用於存儲壓縮之後的page。

參考:MySQL :: MySQL 8.0 Reference Manual :: 15.9.1.2 Creating Compressed Tables

第二種:TPC壓縮

TPC是Transparent page compression的簡稱,也就是 透明頁壓縮。這種方式是主流的壓縮方式。

壓縮是按page爲單位進行壓縮的,一個page的大小默認是16KB,也就是innodb page的默認大小,用於可以通過SQL : select @@innodb_page_size;查詢page的大小;下面都採用一個page爲16KB爲單位。

SQL語句:

create table tt
(
    c1 int primary key,
    c2 varchar(128)
) engine = innodb compression=zlib;
 
create table tt
(
    c1 int primary key,
    c2 varchar(128)
) engine = innodb compression=lz4;
 
create table tt
(
    c1 int primary key,
    c2 varchar(128)
) engine = innodb compression=none;

建表時,compression=後面指定壓縮的方式,支持下面3種寫法:

COMPRESSION [=] {'ZLIB' | 'LZ4' | 'NONE'}
其中zlib和lz4是支持的壓縮方式,NONE表示不壓縮。

一個page變成dirty page之後,後臺線程就會將該dirty page flush到磁盤文件中。確定要flush到磁盤文件時,先將該page進行壓縮(lz4/zlib),壓縮之後以9KB爲例,那麼剩餘的7KB(16K-9K)就會被填充爲0x00,然後flush到磁盤文件後,調用文件系統空洞(Hole Punch)特性(實際上是fallocate())對文件進行“裁剪”,釋放 0x00 佔用的稀疏空間,實際存放到磁盤上的文件大小爲7KB。

當前linux的內核以及大部分的文件系統,例如:XFS、EXT4、ZFS、btrfs、NTFS 等,都支持文件空洞特性。

查看壓縮後的文件佔用的存儲空間大小的SQL如下:

SELECT SPACE, NAME, FS_BLOCK_SIZE, FILE_SIZE, ALLOCATED_SIZE FROM INFORMATION_SCHEMA.INNODB_TABLESPACES WHERE NAME='mysql/bmsql_customer';
FILE_SIZE:表示原始文件的大小

ALLOCATED_SIZE:表示壓縮之後的大小

壓縮率 = ALLOCATED_SIZE / FILE_SIZE

 參考:MySQL :: MySQL 8.0 Reference Manual :: 15.9.2 InnoDB Page Compression

第三種:字典壓縮

基於字典的列壓縮又叫壓縮字典,但只適用於Percona分支。
優點是壓縮率高, 每個列的數據類型都相同;

限制條件:
該列壓縮方式僅用於InnoDB/XtraDB存儲引擎,數據類型支持:
(1)、BLOB (including TINYBLOB, MEDIUMBLOB, LONGBLOG)
(2)、TEXT (including TINYTEXT, MEDUUMTEXT, LONGTEXT)
(3)、VARCHAR (including NATIONAL VARCHAR)
(4)、VARBINARY
(5)、JSON
應用於不受支持的列類型或存儲引擎,則會報錯。

使用MySQL自帶的壓縮鍵功能時的SQL語句:
在創建表語句或更改表語句中增加壓縮標識
(1)、CREATE語句

CREATE TABLE ... (..., foo BLOB COLUMN_FORMAT COMPRESSED, ...);

(2)、ALTER語句

ALTER TABLE ... CHANGE [COLUMN] ... COLUMN_FORMAT COMPRESSED;
 
ALTER TABLE ... MODIFY [COLUMN] ... COLUMN_FORMAT COMPRESSED;
還有一種是用戶自定義壓縮鍵,也就是在在建表時指定壓縮和壓縮鍵。

SQL語句如下:

SET @dictionary_data = 'wall' 'apple' 'peach' 'orange';
 
CREATE COMPRESSION_DICTIONARY numbers (@dictionary_data);
 
CREATE TABLE tt(
        c1 INT,
        c2 text COLUMN_FORMAT COMPRESSED,
        c3 BLOB COLUMN_FORMAT COMPRESSED WITH COMPRESSION_DICTIONARY numbers
      ) ENGINE=InnoDB;
c2採用MySQL默認的壓縮鍵;

c3採用用戶自定義的壓縮鍵;

不過這種方式使用起來還是有爭議的,如果用戶用不好壓縮鍵導致壓縮率低。

其他參考文獻:MySQL :: MySQL 8.0 Reference Manual :: 13.1.20 CREATE TABLE Statement

總之:

現在主流的壓縮方式爲:TPC壓縮和基於字典鍵的壓縮。

如有疑問請發郵件:[email protected]
————————————————
版權聲明:本文爲CSDN博主「一縷陽光a」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/zgaoq/article/details/120522590

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章