本次分享来自社区贡献者张金瑞 。
回想起来,第一次对文件格式有直接的认识,还是在很久很久以前那个MP3随身听流行的年代。那时候,一个MP3随身听的容量通常是128MB;一首.mp3格式的音乐大约为4MB。我是个杰伦粉,当时杰伦发行了大约60首歌曲,而我最大的愿望是在MP3随身听里存下所有杰伦的歌曲。很明显,128MB的随时听最多也只能存30首歌曲,苦恼的博主在一番探索之后,发现手里的MP3播放器不仅能播放.mp3的音乐,还能播放.wma格式的歌曲;而且,一首wma格式的音乐大小只有2MB!有了这个办法,我终于不用每周更换一次MP3里的歌曲了...
【资料图】
那么,为什么差不多音质的一首歌,.wma格式要比.mp3格式占用的空间更少呢?这是因为.wma格式的文件存储音频时,在保持与同码率.mp3文件类似音效的同时,采用了独特的数据编码方式,使得文件所占用的空间更少。同样的,在数据存储领域,不同的文件格式存储同样的数据,其所占用的空间也是不一样的,这取决于每种文件格式的数据编码方式。TsFile 就是一种专门面向时序数据设计的文件格式,其在存储时序数据时能提供更高的数据压缩比例。
1、什么是文件格式?
这可能要从“文件”说起。我们都知道,不同的文件可以解释成不同的含义。拿到一个文件,要想解释出其所表达的信息,就需要知道这个文件中数据的编码方式。这里所提到的“数据在文件中的编码方式”,其实就是对“文件格式”的另一种表述。例如,你之所以能看懂这篇文章,除了你能理解中文之外,还因为我和你都采用了一种默认的文字“从左到右”、“从上到下”的编排方式;假如我突发奇想,将一句话中每相邻的两个字的位置调换一下,可你就能不读了懂。
再或者,假如我今天要写的文章有1000个字,其中“你们”、“我们”、“他们”三个字就占用了大约一半的篇幅。我这个人很懒,觉得不停地写这三个词太累了,所以就用数字“1”代表“你们”,用数字“2”代表“我们”,用数字“3”代表“他们”。“你们和他们都夸我们厉害”写起来就成了“1和3都夸2厉害”(是不是这句话看起来更短了...)。
每种类型的数据都有其特征,我们可以利用其特征设计一种针对该数据类型的编码编排方式,从而降低存储数据的存储空间,同时也让这种针对数据特征的编码方法具备了其实际价值。当然,“存储空间”只是衡量文件格式的一个维度,不同的场景会对文件格式提出不同维度的评价维度,例如“数据写入速度”、“数据查找速度”等。
2、什么是文件?
大家每天使用电脑,都在和一个又一个的文件打交道。记得刚上计算机课的时候,老师常说“计算机存储的东西都是由0和1组成的”。这里提到的0和1是指二进制中的“位”(bit),八个位组成一个“字节”(Byte)。
文件就是由N个字节组成的,文件的大小就是在描述其包含的字节的个数。突然想到,我们经常看到一个词,叫“二进制文件”。广义的二进制文件即指文件,由文件在外部设备的存放形式为二进制而得名;狭义的二进制文件指除文本文件以外的文件。其实文本文件本质上也是二进制文件,只不过其引入了“字符”的概念,且包含多种文件编码格式。
一个文件按照顺序从前到后保存一堆字节,解析文件的工具会按照把这些字节一个个读取出来,按照相应的规则解析成不同的含义。再回到文章最开始的例子,.mp3和.wma都是二进制文件,播放器在遇到这两种文件时,需要将其中的字节读取出来,采用相应的规则对其中的字节进行解析,从而生成最终的音乐信号。
在数据存储领域,有很多文件格式,每种文件格式都有自己组织字节的规则。通常,技术文档在描述文件格式的时候,会将一个文件表示为一个矩形,并在其中用更小的矩形来描述数据的组织方式。这种描述方法通常是为了更好地描述文件格式的特点,但可能会让初学者感到迷惑。
其实在逻辑上,我们可以将一个文件看作是一条一维的线段,最左端为线段的起点,最右端为线段的终点;同时,我们把这条线段分为N份,每份存储一个字节,其中N为该文件中存储的字节的数量。在读取这个文件的时候,计算机可以从左到右依次读取文件中的每个字节,也可以跳到线段中的特定位置去读取特定位置的字节。
所以现在,我们如果想把数据存储在文件中,只需要把数据“转换”成一个个的字节,然后存储在上面提到的“线段”的每个位置中即可。这里的“转换”,其实就是计算机对数据的编码方法,任何数据都可以按照一定的规则转换成字节,只要这个规则是可逆的,其他人在拿到文件后,就可以按照这个规则将字节翻译回数据。不同的转换规则会将同一份数据转换成不同的字节组,不同的文件格式就是在定义这些“规则”。
3、TsFile 就定义了一套转换时序数据的规则
一个时序数据的集合通常会包含多个时间序列,在TsFile 定义的转换规则中,属于同一个时间序列的数据在按照规则转换后,会被尽可能地连续放在一起,也就是我们常说的“列式存储”。之所以将同一列的数据尽可能地放在一起,是因为大部分时序数据的查询通常只会涉及少量序列(甚至是一个序列)的大量数据。这样在读取"线段"(上面对文件的比喻)上的数据时,可以连续地读取线段的某一个或某几个连续的子片段。
另一方面,在存储一列数据时,TsFile 对其进行数据编码。“数据编码”可以将原始数据用更少的字节来表示,从而减少数据存储所占用的空间。举个例子,我们有一句话需要存储在文件中,这句话的内容是“三三三三三三三三”。假如在我们的转换规则中,一个汉字会被转换成两个字节,那么将这句话存储在文件中,需要占用16个字节;如果我们将这句话转化成等价的一句话——“八个三”,那只需要6个字节就可以把这句话存下来(参照下图)。
TsFile 对在处理不同类型的数据时,可以选用不同的数据编码方法,从而结合数据的特点,有效地降低其存储的空间。TsFile 定义的转换规则还提供一些其他特性。例如,TsFile 在存储数据时,不仅将原始数据的字节按照规则保存下来,还将原始数据按照不同的层级计算了聚合索引信息,并将其一并存储在文件中。
综上,TsFile 是一种面向时序数据定义的一种文件格式,其提供了一套将时序数据转换为字节的规则,在减少磁盘占用的前提下,有效地提升了数据查询分析的效率,能够为上层应用提供良好的数据存储和查询支持。
关于我们
作为全球性开源项目,截至目前 Apache IoTDB 已拥有170 名贡献者、1.9KStar、575 Forks。我们为大家提供了参与指南,欢迎越来越多的小伙伴助力 Apache IoTDB 项目的不断发展与前进。
欢迎迈出加入 Apache IoTDB 社区的第一步!
微信群:添加好友qinchuqing/tietouqiao