数据压缩算法

2024-09-16

存储压缩

背景

数据压缩存在于各种场景,视频传输(VR),视频压缩编码–>VR 球形数据的压缩,模型压缩(剪枝) 还存在于各种中间件中,

数据量增加,解决方式通过扩容,或者通过压缩数据,扩容的成本高于压缩,

huffman

高频的字母使用短的信号来编码

信息熵

行式存储和列式存储

行式存储 把原来行的样子原封不动地存储到磁盘上 列式存储 把一列数据挨着放到一起存储,称之为列式存储 空间局部性

列式存储相对于行式存储需要多做的是行转列和列转行

列式存储:(1)相同类型数据在一起,能产生更高的压缩率(2)对列值过滤操作简单,组合不同列结果集更容易(3)在列上做预计算更方便max/min

无损压缩和有损压缩

数据压缩

LZ4 通用二进制压缩

BLOCK数据块–>一层压缩(timestamp,int float,bool等专有压缩)–>二层压缩(通用二进制压缩LZ4)–>存储 timestamp时间列压缩delta-of-delta int类型压缩 zig-zag + simple8b 小整数上效果较好 bool类型列压缩: 1/0二值,bit pack 1bit 浮点类型列压缩: 无损压缩(Google Gorilla)有损压缩 SZ

LZF(redis)

snappy(redis)

ZStd

apache

redis压缩列表

hash-max-ziplist-entries: 使用压缩列表保存时哈希集合中的最大元素个数 hash-max-ziplist-value: 使用压缩列表保存时hash集合中单个元素的最大长度 hash对象保存的键值对数量小于512个,所有的键值对的键和值字符串长度都小于等于64byte时,使用ziplist,否则使用hashtable 一旦从压缩列表转为哈希表,hash类型就会一直用哈希表进行保存而不会再转回压缩列表,在节省内存空间方面哈希表没有压缩列表高效了 压缩列表内存利用率高原因在于连续内存,当一个hash对象只包含少量键值对,并且每个键值对的键和值为小整数或短字符串时,使用压缩列表实现 ziplist是一个经过特殊编码的双向链表,不存储指向前一个链表节点prev和指向下一个链表节点的指针next,而是存储上一个节点长度和当前节点的长度

hive中的数据压缩

ES中的数据压缩

mysql升级同步的数据压缩

MyISAM/InnoDB 都提供compressed data mysql支持压缩的几种方式:

  • 传输压缩 客户端和服务器端之间的数据传输,方式:客户端连接服务时加的–compress选项即可(军),要求cpu性能,网络带宽足够,没必要开启压缩
  • 单表压缩 在创建表的时候指定表的存储为压缩方式 方式:create 或 alter表时指定ROW_FORMAT=COMPRESSED 同时可以指定压缩块的大小KEY_BLOCK_SIZE=(1 2 4 8 16)
  • 单列压缩 调用MYSQL引擎提供的COMPRESS(列名)UNCOMPRESS(列名) 类似于函数 insert into t value(COMPRESS(c1)…) select UNCOMPRESS(c1) from t …

mysql典型的行式存储结构

InnoDB逻辑存储结构,多级存储结构

物理存储结构: 1、ibd 2、frm 3、日志文件组

时序数据库,TDengine 列式存储

总结

专用压缩-压缩侠(模板文件压缩)

存储解压缩

压缩打开对查询和写的性能影响比较大

参考:

apache commons-compress: https://github.com/apache/commons-compress?tab=readme-ov-file redis: ziplist/listpack : hive: