InfluxDB中数据的压缩
Timestamp 压缩
在InfluxDB中数据的压缩主要体现在两个方面,分别是时间戳和Field Value,通过TSM文件的存储我们知道相同的Series Key对应的时间戳和Field value是聚集放在一起的,格式如下:
CRC | FieldValueType | TimeStamp Size | TimeStamps | values |
---|---|---|---|---|
4 bytes | 1 bytes | N byte | N byte | N byte |
TimeStamps和values都是压缩后的数据块,先来看时间戳的压缩,时间戳目前有两种压缩方式分别是Run-Length-Encoding(RLE)和Simple8b,还有可能不压缩。所以TimeStamps的存储结构就有三种可能,通过前4bit来表示它属于存储方式。具体使用那种方式取决于时间数据的特点,判断逻辑如下图所示:
图中的Delta是取的差值,比如数组长度为n,从数据尾部开始,后一个减去前一个元素的差值存放在替换后一个原来的值,直到第一个元素。差值有n-1个,然后判断这n-1个差值是否全部相同,如果相同采用压缩效率最高的RLE,如果最大的差值小于(1<<60) - 1,采用simple8b压缩,至于为什么这个数后面解释。如果大于则不压缩,将每个时间数据都按8byte存。
1. RLE
如果所有的差值都相同,那么采用TLE方式编码,存储格式如下:
Encode Type | Divisor | First Timestamp | DeltaValue | N |
---|---|---|---|---|
4 bit | 4 bit | 8 byte | 8 byte | 8byte |
-
Encode Type表示编码方式,这里是2
-
Divisor意思是是除数的log10的值,采用4bit存储。差值都为1000000,那么Divisor存储的值为6
-
First Timestamp就是第一个时间戳的值
-
DeltaValue为差值
-
N表示有多少个差值
2. Packed编码
差值数组中数据的最大值不大于(1 << 60)- 1 。使用该算法进行编码时,其存储结构如下:
Encode Type | Divisor | First Timestamp | Simple8bData |
---|---|---|---|
4 bit | 4 bit | 8 byte | - |
前三个字段的意思与RLE相同,不过Encode Type具体的值为1,接下来看下Simple8b的压缩方式是将多个小与(1<<60)-1的整数压缩到一个64位的整数中,它是根据整数集合的特点来决定如何压缩,共有16种压缩方式,具体如下
┌──────────────┬─────────────────────────────────────────────────────────────┐
│ Selector │ 0 1 2 3 4 5 6 7 8 9 0 11 12 13 14 15│
├──────────────┼─────────────────────────────────────────────────────────────┤
│ Bits │ 0 0 1 2 3 4 5 6 7 8 10 12 15 20 30 60│
├──────────────┼─────────────────────────────────────────────────────────────┤
│ N │ 240 120 60 30 20 15 12 10 8 7 6 5 4 3 2 1│
├──────────────┼─────────────────────────────────────────────────────────────┤
│ Wasted Bits│ 60 60 0 0 0 0 12 0 4 4 0 0 0 0 0 0│
└──────────────┴─────────────────────────────────────────────────────────────┘
- 给以一个整数集合,Simple8b从 从 0 到 15 ,依次检查是否满足压缩条件
- 如果符合某种被压缩,则使用对应规则执行压缩过程,将Selector编号写入目标数组,接着将对应的N个整数写入对应的bits中。
- 将剩余未压缩数组从步骤1开始继续执行,直到集合中的数据全部被压缩
为什么只有小于(1<<60)-1的整数才能使用Simple8b编码呢?因为编码的后64位前4位要存放Selector,
如果你想知道跟多细节,可以点这里了解go的实现以及测试代码
3. Raw编码
这种编码方式未对数据进行压缩,为了保持格式一致,还多了一个byte存放Encode Type,存储结构如下:
Encode Type | TimeData |
---|---|
1byte(高四位) | 8*N byte |
这里的每个时间戳都适用8byte来存储。
以上是Influxdb目前所有实现了对时间戳压缩的方式,但是在文档中提到了考虑未来实现PFOR压缩。
整数(64位)压缩
在Inlfuxdb中只有一种整数类型即int64,现将所有整数通过zigzag转换为正整数。zigzag相当于把符号位放在了最低位,从而有利于小整数的压缩。zigzag编码操作为(n << 1) ^ (n >> 63),如果zigzag编码后的值都小于(1 << 60) - 1),那么采用Simple-8b压缩,如果有些值大于(1 << 60) - 1),那么不进行压缩该块。如果所有的值都相同采用RLE编码。和时间戳的压缩的存储格式类似,数据块的前4bit为压缩方式,第二个字节开始存放数据。
Float 压缩
FLoat类型使用Facebook Gorillal的实现XOR算法进行编码,大致如下:
-
第一个Value存储时不做任何压缩。
-
后面产生的每一个Value与前一个Value计算异或值
如果XOR值为0,即两个Value相同,那么存为0,只占用一个bit。
如果XOR为非0,那么第一个bit存为1,计算XOR中位于前端的和后端的0的个数,即Leading Zeros与Trailing Zeros。
- 如果Leading Zeros与Trailing Zeros与前一个XOR值相同,则第2个bit值存为’0’,紧跟着去掉Leading Zeros与Trailing Zeros以后,只存有效XOR值部分。
2.1) 如果Leading Zeros与Trailing Zeros与前一个XOR值相同,则第2个bit值存为’0’,而后,紧跟着去掉Leading Zeros与Trailing Zeros以后的有效XOR值部分。
Leading Zeros与Trailing Zeros与前一个XOR值不同,则第2个bit值存为’1’,紧跟着5个bits用来描述Leading Zeros的值,再用6个bits来描述有效XOR值的长度,最后再存储有效XOR值部分。
上一篇: 消息中间件ActiveMQ
下一篇: 在eclipse中输入命令行参数
推荐阅读
-
Java中excel表数据的批量导入方法
-
Android开发中数据库升级且表添加新列的方法
-
sqlserver isnull在数据库查询中的应用
-
一次性压缩Sqlserver2005中所有库日志的存储过程
-
SQLServer中数据库文件的存放方式,文件和文件组
-
C#如何将Access中以时间段条件查询的数据添加到ListView中
-
iOS中的NSURLCache数据缓存类用法解析
-
iOS App开发中Core Data框架基本的数据管理功能小结
-
winform中的ListBox和ComboBox绑定数据用法实例
-
ASP.NET 2.0中的数据操作之八:使用两个DropDownList过滤的主/从报表