记 doris 加载压缩文件(lzo、snappy)pr

做了一个case,是doris支持加载lzo压缩文件。[improvement](load) Enable lzo & Remove dependency on Markus F.X.J. Oberhumer's lzo library by HowardQin · Pull Request #30573 · apache/doris (github.com)

其实doris里已经支持了 lzo,这个case源自一个issue,[Enhancement] broke load enhanced · Issue #29406 · apache/doris (github.com) 

issue中说不支持lzo和snappy,我猜是加载lzo压缩的hive表文件,报错不支持,snappy他应该没试过,我试过了,已经支持了snappy。

对于这些压缩格式和压缩文件,我也是第一次接触,网上了一些介绍,lzo 是一种压缩算法,它的开源库使用很简单,就是一个函数:

压缩时,接受一个数据块的内存地址和长度,压缩以后的数据块,放在另一个内存地址,压缩以后的大小,作为参数返回,这些内存的分配要事先分配好。

解压时,接受一个已压缩的数据块,解压以后的数据块,放在另一个内存地址,解压后的大小,作为参数返回。

这里要分清两个概念:lzo是压缩算法,它只管把一块大的数据压缩成一块小的数据,但是要把一个文件分成几个数据块来压缩,压缩以后怎么保存到磁盘,以便于解压缩,这些lzo是不管的,也不会做规定,于是就有了lzop,它是一个把普通文件做lzo压缩和解压的工具(可执行程序),它定义了保存lzo压缩文件的格式,可以理解lzop是保存用lzo压缩算法压缩以后的数据的一个容器(包装盒),而这个lzop也是有格式的。

一般来说,要把一个大文件,做lzo压缩并保存,要把这个大文件分成一个个小块,然后对这些小块调用压缩函数进行压缩,然后保存,而不是压缩整个文件。

这就有个问题,压缩以后的数据块,保存时不能简单的,紧挨着写到文件,而是在写入每个压缩后的数据块时,数据块的大小也要写到文件里,这样解压时先读取大小,再读入所指示的数据块,再传给解压函数才能正确解压。

上面只是一种最简单的格式,实际格式要稍微复杂一点,这种在压缩文件中,能被完整解压的一块数据和相关信息,有一个专业术语,称为帧格式(frame format),lzop定义了lzo压缩文件的帧格式,还定义了文件头,是这样的:

1、lzo压缩文件的开头的是9个字节的magic字符串,值是固定的,估计是作为lzop压缩文件的标识。

2、接下来是2个字节的version,这个指是lzop这种封装格式的版本。

3、接下来是2个字节的lib_version,这是指lzo压缩算法库的版本,要注意与前一个version的区别。

4、接下来是2个字节的version_needed,我搞不明白这个是做什么用的,但是这个值好像应该与2中的version一样。

5、接下来是1个字节的method,lzop压缩的文件是文件头+一个一个的帧,每个帧封装着一块压缩后的数据,其实这个压缩的算法并不一定要用lzo,这种封装压缩文件的格式有一定的通用性,也可以用于封装其它压缩算法压缩的数据,于是这个method就是用于指示帧中的压缩数据所使用的压缩算法,1~3都属于lzo算法。

6、接下来是1个字节的level,应该是lzo的压缩率 1~9,越小表示压缩的更快但牺牲压缩率,越大表示压缩的更慢但压缩率高,不过我看doris的代码里直接忽略了level的值估计解压函数能自动处理。

7、然后是4个字节的flag,里面以位图的形式,存储了文件头的checksum的类型,每个数据帧中数据块压缩和解压以后的checksum的类型,还有一些其它信息。

8、然后是12个字节的 mode 和 mtime,我也不知道是做啥用的,看doris代码是直接略过的,注意doris代码只有解压lzop文件。

9、然后是1个字节的文件名长度,“文件名”就是要解压的这个lzop文件名本身,文件名长度后面,紧跟着就是文件名字符串,注意,这个字符串不是以'\0'结尾的,而且通过长度控制不越界,读到内存中要加'\0',或std::string(ptr, len)转为string。

11、然后是4个字节的文件头数据的checksum,这个checksum是从文件头开始,到这4个字节以前的所有数据的校验和,“文件头数据”不包括文件头的checksum本身。

12、然后就是一帧一帧的压缩数据了。

每一帧的格式如下:

1、4个字节的解压以后的数据块长度

2、4个字节的压缩以后的数据块长度

3、4个字节的解压以后的数据块的checksum

4、4个字节的压缩以后的数据块的checksum

5、压缩以后的数据块,长度是在2中记录的

其它的压缩算法和它们的压缩文件封装格式,也存在相似的模式,也存在一个文件头和帧格式问题。

在处理数据帧的时候,还有个校验和的计算问题,主要是crc32和adler32两种算法,它们都会计算数据块然后返回32位的校验和(其实是少于32位的),网上有许多关于crc32的算法科普和源码,我理解的也不深,只是从使用角度理解,对我来说crc32和md5、sha256差不多,都是校验数据块一致性的用的,应该只能检验错误,没有纠错功能。

关于crc32可以参考:

[原创]CRC技术的实现与破解(10.21更新)-软件逆向-看雪-安全社区|安全招聘|kanxue.com

哦,还有,这些压缩算法都是无损压缩算法,还有所谓的“流式”其实就是一个数据帧一个数据帧的解压,然后把解压后的数据存储起来或发送出去。

你可能感兴趣的:(Doris,信息技术笔记,压缩)