在 MySQL 官方文档中, 透明表空间压缩称为 InnoDB Page Compression 以区别于原来的 InnoDB Table Compression,但是其实它们都是基于页(Page)的压缩。
透明表空间压缩应该写成 InnoDB Transparent Page Compression 更为贴切。
官方文档:https://dev.mysql.com/doc/refman/5.7/en/innodb-page-compression.html
官方博客:https://mysqlserverteam.com/innodb-transparent-page-compression/
透明表空间压缩的创建
-- 透明表空间压缩的创建
mysql> create table trans_test_1 (a int ) compression="zlib"; -- 使用zlib的压缩算法
Query OK, 0 rows affected, 1 warning (0.14 sec) -- 存在warning
mysql> create table trans_test_2 (a int ) compression="lz4"; -- 使用lz4的压缩算法
Query OK, 0 rows affected, 1 warning (0.13 sec)
mysql> alter table trans_test_2 compression="zlib";
Query OK, 0 rows affected (0.05 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql> optimize table trans_test_2; -- 官方文档中提及如果是已存在的表,需要执行optimize table操作
+------------------------+----------+----------+-------------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+------------------------+----------+----------+-------------------------------------------------------------------+
| burn_test.trans_test_2 | optimize | note | Table does not support optimize, doing recreate + analyze instead |
| burn_test.trans_test_2 | optimize | status | OK |
+------------------------+----------+----------+-------------------------------------------------------------------+
2 rows in set, 1 warning (0.18 sec) -- 还是有warning
mysql> show create table trans_test_1\G
*************************** 1. row ***************************
Table: trans_test_1
Create Table: CREATE TABLE `trans_test_1` (
`a` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMPRESSION='zlib'
1 row in set (0.00 sec)
-- zlib的压缩比更高
-- lz4的速度更快
在上述创建过程中,并没有指定页大小,而是使用了文件系统(filesystem)层中稀疏文件的特性,来达到压缩的目的。
稀疏文件
如上图所示,可以简单的理解为,文件中数据连续为0的部分不占用磁盘空间。
# 创建一个零时的,且数据部分全0的文件
shell> dd of=sparse-file bs=1k seek=5120 count=0 # 创建5M大小,内容全为0的文件
0+0 records in
0+0 records out
0 bytes (0 B) copied, 6.7872e-05 s, 0.0 kB/s # 无数据写入到磁盘
shell> ls -hl sparse-file
-rw-r--r--. 1 root root 5.0M Jan 5 00:07 sparse-file # 显示该文件大小为5M
shell> du --block-size=1 sparse-file # 检查文件占用多少空间
0 sparse-file # 显示占用空间为0
- 压缩后,原来 16K 的数据压缩成了 4K
- 剩余的 12K 空间用特殊的字符填充(比如说是0)
- 在写入文件系统时调用 Punching holes 写入,实则只写入 4K 的数据
- 被填充的 12K 的空间,可以提供给后序的插入,更新等使用
- 从 InnoDB 的角度看还是 16K 的页大小,只是文件系统知道该页只需要 4K 就能够存储(对 InnoDB 是透明的)
- SpaceID 和 PageNumber 的读取方式没有改变(细节由文件系统屏蔽)
由于文件系统的快大小是 4K,所以压缩后存储的空间也是 4K 对齐的
- 比如 16K 压缩成了 10K,那就需要3个 4K 去存储
操作系统要求mysql> desc information_schema.INNODB_SYS_TABLESPACES;
+----------------+---------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------------+---------------------+------+-----+---------+-------+
| SPACE | int(11) unsigned | NO | | 0 | |
| NAME | varchar(655) | NO | | | |
| FLAG | int(11) unsigned | NO | | 0 | |
| FILE_FORMAT | varchar(10) | YES | | NULL | |
| ROW_FORMAT | varchar(22) | YES | | NULL | |
| PAGE_SIZE | int(11) unsigned | NO | | 0 | |
| ZIP_PAGE_SIZE | int(11) unsigned | NO | | 0 | |
| SPACE_TYPE | varchar(10) | YES | | NULL | |
| FS_BLOCK_SIZE | int(11) unsigned | NO | | 0 | | -- 文件系统的块大小
| FILE_SIZE | bigint(21) unsigned | NO | | 0 | | -- 文件大小
| ALLOCATED_SIZE | bigint(21) unsigned | NO | | 0 | | -- 文件实际分配的大小
| COMPRESSION | varchar(5) | NO | | | |
+----------------+---------------------+------+-----+---------+-------+
12 rows in set (0.00 sec)
- 比如 16K 压缩成了 10K,那就需要3个 4K 去存储
操作系统以及内核
- RHEL7 kernel >= 3.10.0-123
- Debian 7 kernel >= 3.2
- Ubuntu 12.04LTS kernel >= 3.2
- Ubuntu 14.0.4LTS kernel >= 3.13
- Oracle 和 Suse 可以参考官方文档
- 文件系统
- 支持 Hole Punch
- 比如 XFS,EXT4,NTFS 等 ```sql mysql> show warnings; +————-+———+—————————————————————————————————————————————————————————————-+ | Level | Code | Message | +————-+———+—————————————————————————————————————————————————————————————-+ | Warning | 138 | InnoDB: Punch hole not supported by the file system or the tablespace page size is not large enough. Compression disabled | +————-+———+—————————————————————————————————————————————————————————————-+ 1 row in set (0.00 sec)
— 原因1是我的内核版本太低,不支持 — 原因2是因为general方式安装的mysql不支持透明压缩,需要自己编译 — http://bugs.mysql.com/bug.php?id=77974 ```
作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/nf4rrq 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。