此文已由作者王慎为授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

MySQL 5.7中包括了很多让人耳目一新的新特性,其中就包括了InnoDB Transparent Page Compression,姑且称之为InnoDB透明页压缩。其实透明页压缩这个东西,早就关注过,其用到了sparse file和hole punching技术,但一直没能将这两种技术跟InnoDB压缩联系起来。最近花了点时间了解了下。

熟悉InnoDB的同学都知道,InnoDB从MySQL 5.1版本开始就支持压缩,提供zlib压缩算法,是记录压缩(record compress),曾大概看过InnoDB这部分相关的源码,逻辑比较复杂,如果对InnoDB page的组织结构不了解,相信很难看出个所以然,该压缩是页感知的(page aware),即需要知道页里面记录是怎么保存的。与之相反,MySQL 5.7最新支持的压缩是页透明的(page transparent),当然,页首尾的元数据是不压缩的,不关心这个页里面保存的是什么内容,可以理解为页/块压缩(page/block compress,本文将块和页混用)。

假设有个16KB的InnoDB页P1,通过块压缩为11KB,如果表空间使用的文件系统在mkfs时指定block size为4KB,那么只需要使用3个文件块来保存11KB的数据,节省1个文件块即4KB的空间。那么是不是说InnoDB下个页P2的数据直接从所节省的这4KB开始写入吗,答案是否定的。

InnoDB透明页压缩不会改变表文件的结构,我们可以理解为每页都占据了文件中4个块的大小,页压缩后的最终大小不会影响每个页在表文件中的起始偏移位置。即第k个页的数据,还是从表文件第4*k个块开始写入。问题来了,为什么不呢,因为压缩页经过修改后,再次压缩后的大小是不可知的,可能本来压缩后的大小为11KB,再次压缩就变成15KB了,那么仍需要4K文件块来保存,如果文件第4*n+3个块已经被写入了P2的数据,P1再次压缩后多出来4K数据就没地方放了。

从上段描述来看,不管P1被压缩成什么熊样,P2仍然需要从表文件的第4*n+4个偏移块开始写入数据,这种压缩并没有改变文件逻辑大小。虽然压缩后,IO是小了,但4KB的IO相比16KB的IO并不能带来多大的性能提升。然并卵!

怎样才能节省被压缩后释放的空间呢,这就需要用到文件系统/操作系统内核层面的技术 - sparse file,简单来说,sparse file是这样的文件, file 1大小是12KB,但是其实只占用首尾2个文件块共8KB的磁盘空间,中间4KB由于没有真实数据,并未分配磁盘空间,或者本来已经分配了,但又被回收了,像是中间被挖了个洞(punch hole)。这被挖的4KB,可以被文件系统用来分配给其他文件保存数据。如果中间4KB的数据被用户填上了呢,没事,文件系统分配一个新的空闲快给file 1即可。关于sparse file更详细的介绍参见参考文献。当然这可能会导致数据库IO不连续。

通过上面的描述,相信很容易就能够将sparse file技术应用到InnoDB透明页压缩上。不再赘述,只放一张图。

为什么InnoDB要另辟蹊径,采用新的压缩方案,不再原来的压缩实现上进行优化呢,可能有以下两点原因:

首先,原有的记录级压缩,代码实现复杂的,需要基于不同的页类型采用不同的处理方式,需要熟悉InnoDB的索引和页结构,代码封装性较差,添加新的压缩算法或进行性能优化提升较费劲,所以一直仅支持zlib。在这个基础上进行优化提高较困难。这个观点得到MySQL官方的验证,详见参考文献中的官方描述。

其次,相对于原来的记录级压缩,新方案更加灵活,因为压缩算法是保持在InnoDB页的元数据中,理论上可以做到同个表中不同页采用了不同的压缩算法,比如根据不同页类型来决定是否压缩,采用某种压缩算法(当然目前MySQL官方还没这么做)。现实中,也会存在同个表包括多种压缩算法的场景,因为用户可以动态修改压缩算法(也可以启动和关闭压缩),而动态修改并不是说把已经压缩的页马上使用新的压缩算法重新压一次,而是对新产生或更新的页起作用,这就会导致有些页是不压缩的,有些页是采用zlib,有些采用lz4。吐槽下,为什么InnoDB还不支持snappy或quicklz呢。

参考文献:

http://dev.mysql.com/worklog/task/?id=7696

http://mysqlserverteam.com/innodb-transparent-page-compression/

http://mysqlserverteam.com/innodb-transparent-pageio-compression/

https://wiki.archlinux.org/index.php/Sparse_file

网易云免费体验馆,0成本体验20+款云产品!

更多网易技术、产品、运营经验分享请点击

相关文章:
【推荐】 Java web 服务启动时Xss溢出异常处理笔记
【推荐】 谈谈iOS开发如何写个人中心这类页面--静态tableView页面的编写
【推荐】 云计算节点故障自动化运维服务设计

InnoDB透明页压缩与稀疏文件的更多相关文章

  1. InnoDB页压缩技术

    Ⅰ.想起一个报错 1.1 创建表报错 (root@localhost) [(none)]> create tablespace ger_space add datafile 'ger_space ...

  2. MySQL · 引擎特性 · InnoDB 数据页解析

    前言 之前介绍的月报中,详细介绍了InnoDB Buffer Pool的实现细节,Buffer Pool主要就是用来存储数据页的,是数据页在内存中的动态存储方式,而本文介绍一下数据页在磁盘上的静态存储 ...

  3. 第17章 内存映射文件(3)_稀疏文件(Sparse File)

    17.8 稀疏调拨的内存映射文件 17.8.1 稀疏文件简介 (1)稀疏文件(Sparse File):指的是文件中出现大量的0数据,这些数据对我们用处不大,但是却一样的占用空间.NTFS文件系统对此 ...

  4. InnoDB 数据表压缩原理与限制

    http://liuxin1982.blog.chinaunix.net/uid-24485075-id-3523032.html 压缩理念 通过提高CPU利用率和节约成本,降低数据库容量及I/O负载 ...

  5. 14.5.4 InnoDB File-Per-Table Tablespaces 每个表一个文件

    14.5.4 InnoDB File-Per-Table Tablespaces 每个表一个文件 从历史上看, 所有的InnoDB 表和索引是存储在system 表空间, 这个整体的方法是针对机器专注 ...

  6. Linux下稀疏文件的存储方式

    写在前面:本博客为本人原创,严禁任何形式的转载!本博客只允许放在博客园(.cnblogs.com),如果您在其他网站看到这篇博文,请通过下面这个唯一的合法链接转到原文! 本博客全网唯一合法URL:ht ...

  7. InnoDB数据页结构

    前言 ​ 关于数据库我们知道是通过内存对磁盘进行操作的,也知道数据会落实到磁盘上,但是数据在磁盘上的存储结构可能大家还不是很清楚. ​ MySQL服务器上负责对表中的数据的读取和写入的工作的部分是存储 ...

  8. InnoDB存储引擎的表空间文件,重做日志文件

    存储引擎文件:因为MySQL表存储引擎的关系,每个存储引擎都会有自己的文件来保存各种数据.这些存储引擎真正存储了数据和索引等数据. 表空间文件 InnoDB存储引擎在存储设计上模仿了Oracle,将存 ...

  9. SQL Server ->> Sparse File(稀疏文件)

    Sparse File(稀疏文件)不是SQL Server的特性.它属于Windows的NTFS文件系统的一个特性.如果某个大文件中的数据包含着大量“0数据”(这个应该从二进制上看),这样的文件就可以 ...

随机推荐

  1. python堆排序实现TOPK问题

    # 构建小顶堆跳转def sift(li, low, higt): tmp = li[low] i = low j = 2 * i + 1 while j <= higt: # 情况2:i已经是 ...

  2. [洛谷P3512 [POI2010]PIL-Pilots]

    题目链接: 传送门走这里 题目分析: 感觉不是很难啊--不像是蓝题(AC量也不像)恶意评分? 少打了一个+1调了半天,就这样居然还能过60pts?我思路和题解第一篇高度重合是什么鬼啊,太过分了吧本来还 ...

  3. 洛谷 P1445 [Violet]樱花

    #include<cstdio> #include<algorithm> #include<cstring> #include<vector> usin ...

  4. 转 PHP scandir() 函数

    实例 列出 images 目录中的文件和目录: <?php $dir = "/images/"; // 以升序排序 - 默认 $a = scandir($dir); // 以 ...

  5. toLocaleSting()

    之前一直忽略了这一方法,直到前天的笔试题,两种方式实现如下功能... 1234567890→1,234,567,890 当时我的思路是这样的:1.字符串反转,插入逗号,再反转 2.求余数,将字符串一分 ...

  6. scau 1144 数星星 bit + 扫描线的思想

    这题如果用二维树状数组,则会直接爆内存. 那么可以运用扫描线的思路. 就是,它同时被x和y限制了,那么可以在查询的时候,确保x先满足了,(把x按小到大排序) 然后就相当于是关于y的一个一维bit了, ...

  7. 将php数组传递到js—json_encode(),json_decode()

    json_decode(),对一个json字符串进行解码,json_encode()是生成一个json字符串 上面的解释很清楚了,关于php里数组赋值的问题,列举如下: <?php //对象 c ...

  8. AJPFX对选择和冒泡两种排序的理解

    冒泡排序和直接选择排序都是排序中比较简单和容易实现的算法,先简单说说两者的区别:先以按照元素从小到大为:冒泡排序:将相邻元素两两比较,如果有比较大的,就把比较大的放在右边,这样的结果就是一轮排序完毕后 ...

  9. Java GC机制简要总结(Java垃圾回收的基本工作原理)

    第一次编辑 2019-05-07 01:09:39 垃圾回收的对象 程序中的不可用对象(不存活的对象,没有任何引用),或者无用的变量信息等,在程序中长期存在会逐渐占用较多的内存空间,导致没有足够的空间 ...

  10. JS实现让其他浏览器自动转至微信浏览器打开链接

    //判断是否是pc function is_pc() { var sUserAgent = navigator.userAgent.toLowerCase(); var bIsIpad = sUser ...