天天看點

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。

MySQL中的表壓縮功能

目前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]