🍋

CAl (3)数据库压缩算法

 

MySQL 压缩

  • InnoDB 中默认使用 zlib 算法进行压缩,也可以选择 snappy、quicklz 等,详细的对比可以参考这里的一篇文章,简而言之: snappy 和 quicklz在压缩比和cpu消耗上保存了较好的平衡,这两种算法在新开发的软件中使用更为广泛,包括TokuDB、MongoDB等。
  • rocksdb 引擎的压缩率一般更高,其使用了 前缀编码和零填充行元数据的技术,提高了数据的压缩率,myrocks 的文档里面给了这样一个例子, 同样的数据在 InnoDB 占用 1172GB,在 MyRocks 中占用 574GB。

HBase 压缩

目前 HBase 可以支持的压缩方式有 GZ(GZIP)、LZO、LZ4 以及 Snappy。 它们之间的区别如下:
  • GZ:用于冷数据压缩,与 Snappy 和 LZO 相比,GZIP 的压缩率更高,但是更消耗 CPU,解压/压缩速度更慢。
  • Snappy 和 LZO:用于热数据压缩,占用 CPU 少,解压/压缩速度比 GZ 快,但是压缩率不如 GZ 高。
  • Snappy 与 LZO 相比,Snappy 整体性能优于 LZO,Snappy 压缩率比 LZO 更低,但是解压/压缩速度更快。
  • LZ4 与 LZO 相比,LZ4 的压缩率和 LZO 的压缩率相差不多,但是LZ4的解压/压缩速度更快。
下面的表格来自阿里云:
业务类型
无压缩表大小
LZO(压缩率/解压速度MB/s)
ZSTD(压缩率/解压速度MB/s)
LZ4(压缩率/解压速度MB/s)
监控类
419.75T
5.82/372
13.09/256
5.19/463.8
日志类
77.26T
4.11/333
6.0/287
4.16/496.1
风控类
147.83T
4.29/297.7
5.93/270
4.19/441.38
消费记录
108.04T
5.93/316.8
10.51/288.3
5.55/520.3

MongoDB 压缩

在MongoDB 中,WiredTiger为集合提供三个压缩选项:
  • 无压缩
  • Snappy(默认启用) – 很不错的压缩,有效利用资源【在各种文本测试场景中,压缩率约在54%~55%】
  • zlib(类似gzip) – 出色的压缩,但需要占用更多资源
  • zstd(从MongoDB 4.2开始支持)
 

ClickHouse压缩

其中使用的 通用压缩算法其实和别的数据库差不多,比如:
  • LZ4:非常高效的压缩算法,在SLS内部大量使用,压缩和解压性能都极强,尤其是解压性能可达到单核4GB/s。缺点是压缩率有点低(但是在日志场景可以达到5-15倍的压缩率,还是非常适用的)
  • ZSTD:虽然压缩/解压效率不如LZ4,但是也可以达到单核400M/s的压缩和1G/s左右的解压
列/时序压缩算法:适合按列存储数据,尤其适合时序场景,我们已经看到了 gorilla 在prometheus tsdb 中的成功应用,在适合的场景下,这种算法的压缩效果可能会达到惊人的 10% 甚至 1%,这部分的压缩方式和设计思想尤其值得我们学习。
  • Delta,其思想就是存储变化值,比如这样的数据: 1, 2, 3, 3, 2, 4, 会被压缩成 1(base), 1, 1, 0, -1, 2
  • DoubleDelta:存储的是 delta 的 delta,比如 1589636543 1589636553 1589636563 1589636573 1589636583 1589636594 1589636603, 会被压缩成 1589636543(Base) 10(Delta) 0 0 0 1 -1 ...
  • Gorilla: 其实 DoubleDelta 是参考的 facebook 的 Gorilla 论文,而 clickhouse 中的 gorilla 则是针对 double 数值的一种变化。通过异或的形式来计算前后的 Delta,来解决 DoubleDelta 对于 double 数据压缩很差的问题。
  • T64:2019年新引入的编码方式,T64只支持int/uint类型的压缩。首先压缩前拿到数据类型,然后会计算数据的Max Min,根据Max Min获得有效的bit位,然后把数据映射到64*bit位的空间,由于64是固定的,因此叫做T64。
类似 Delta、DoubleDelta 的算法存在的一个问题是,取数据需要一整块全部取出来,才能恢复出数据,有点类似视频压缩中,需要关键帧,仅仅用 p 帧无法恢复数据。