在上述InfluxDB压缩算法的文章中,描述了具体使用的压缩算法,但单就这些算法并不能指导实践,为此本文针对不同的数据类型总结了压缩率,并给出了能提高压缩率的实际方法,写点姿势,希望能在实际生产中指导实践。
1 | influx_inspect dumptsm xxx.tsm |
上述命令是InfluxDB提供的一个inspect tsm文件的工具,运行上述命令会产生如下输出1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18Summary:
File: /tmp/tsm1-test412750211/tsm1test039799558
Time Range: 2017-04-12T02:57:16.000352Z - 2017-05-05T06:30:35.900035Z
Duration: 555h33m19.899683s Series: 1 File Size: 217812294
Statistics
Blocks:
Total: 1 Size: 217812245 Min: 217812241 Max: 217812241 Avg: 217812245
Index:
Total: 1 Size: 36
Points:
Total: 20000000
Encoding:
Timestamp: none: 0 (0%) s8b: 1 (100%)
Float: none: 0 (0%) gor: 1 (100%)
Compression:
Per block: 10.89 bytes/point
Total: 10.89 bytes/point
其中statistics
包含重要信息,首先总共的点数是2000w,其次timestamp的压缩方法是simple8b(100%),float使用的gorilla(100%)的压缩方法,最后,平均每个点占用的空间是10.89bytes。
下面我们从不同的数据类型入手,探究多种写点的姿势对压缩率的影响。
bool类型的数据
策略一,时间戳乱序写入
1 | values := make([]tsm1.Value, 0, 20000000) |
inspect结果1
2
3Encoding:
Timestamp: none: 1 (100%)
Bool: none: 0 (0%) bp: 1 (100%)
磁盘文件大小:155MB
策略二, 时间戳等差数列写入
1 | values := make([]tsm1.Value, 0, 20000000) |
inspect结果1
2
3Encoding:
Timestamp: none: 0 (0%) s8b: 0 (0%) rle: 1 (100%)
Bool: none: 0 (0%) bp: 1 (100%)
磁盘文件大小:2.4MB
策略三,时间戳升序写入
1 | values := make([]tsm1.Value, 0, 20000000) |
inspect结果1
2
3Encoding:
Timestamp: none: 0 (0%) s8b: 1 (100%)
Bool: none: 0 (0%) bp: 1 (100%)
磁盘上文件大小:105MB
结论
2000w个bool类型的数据实际上是2000w个bool类型的数据+2000w个int64的时间戳,bool类型数据压缩很固定,只有2.4MB,而且对压缩率基本没有影响;
而int64时间戳的才是真正的影响压缩率的大头,从上述策略中得出,时间戳等比数列的压缩率最高,其次是升序时间戳,最后是完全无序随机。
InfluxDB的主要使用场景是IoT时序数据,这些数据绝大部分都遵从时间升序的规律,甚至对于一些定时采样的数据,时间戳甚至是等比数列的,也就可以使这些数据有相当大的压缩率。
int类型的数据
上述分析,已经得出时间戳对数据的影响了,2000w个int类型的数据实际上是4000w个int64的数据
时间戳等比数列 +随机int数据
1 | values := make([]tsm1.Value, 0, 20000000) |
inspect 结果1
2
3Encoding:
Timestamp: none: 0 (0%) s8b: 0 (0%) rle: 1 (100%)
Int: none: 0 (0%) s8b: 1 (100%)
磁盘文件大小:99MB
时间戳等比数列 +升序int数据
1 | values := make([]tsm1.Value, 0, 20000000) |
inspect 结果1
2
3Encoding:
Timestamp: none: 0 (0%) s8b: 0 (0%) rle: 1 (100%)
Int: none: 0 (0%) s8b: 1 (100%)
磁盘文件大小:77MB
时间戳等比数列 + 整体升序,局部随机数据
1 | values := make([]tsm1.Value, 0, 20000000) |
inspect结果1
2
3Encoding:
Timestamp: none: 0 (0%) s8b: 0 (0%) rle: 1 (100%)
Int: none: 0 (0%) s8b: 1 (100%)
磁盘文件大小:63MB
结论
在上述策略中,我们排除了时间戳对数据压缩的影响,所有的时间戳都是递增的,在这种情况下,压缩的效率就完全取决于int数据了。
从三个策略看,int的压缩全部是s8b的压缩,而且数据是否有序这个因素影响并不是很显著。
float类型的数据
为了排除时间戳对压缩率的影响,我们同样采取int类型数据的三种策略
时间戳等比数列 +随机float数据
1 | values := make([]tsm1.Value, 0, 20000000) |
inspect 结果:1
2
3Encoding:
Timestamp: none: 0 (0%) s8b: 0 (0%) rle: 1 (100%)
Float: none: 0 (0%) gor: 1 (100%)
磁盘文件大小: 157MB
时间戳等比数列 +升序float数据
1 | values := make([]tsm1.Value, 0, 20000000) |
inspect结果:和上述结果一样
磁盘文件大小:119MB
时间戳等比数列 + 整体升序,局部随机数据
1 | values := make([]tsm1.Value, 0, 20000000) |
inspect结果:和上面一样
磁盘文件大小:157MB
结论
float的压缩和int的压缩类似,所有的float压缩也全是用的gorrila的压缩方法,且和是否有序没有显著关系。
总结
首先,InfluxDB中需要压缩的数据由两部分构成,实际的数据(int,float,boo,string)和timestamp(int),且一个实际的数值对应一个实际的时间戳,时间戳的个数占比是高达50%的,所以时间戳的压缩比的高低直接关系着整体数据的压缩比的高低;timestamp的压缩方法是s8b的压缩方法,所以在时间戳有序的情况下,能有效提高压缩比。
其次,bool数据的压缩是恒定的,一个bool值占一个bit,无论什么情况下都是这样的;float使用的gorrila的压缩方法,也没有对数据顺序的要求。
最后可以看出InfluxDB对数据的压缩率很大情况下取决于数据的时间戳是否有序,越有序(升序)那么压缩率越高。
欢迎留言讨论~