问题描述

我们知道,对于时序数据而言,每一个时间序列的数据,都有一个对应的时间戳,但是有没有必要为每一个时间序列都存一个时间戳,这个是值得商榷的,这得根据具体的时间序列的对齐程度去判断。

比如对于第一种写入情况而言,这四个时间序列的时间戳都是一样的,对齐程度很高,所以在磁盘上,只存一列时间戳,对应这四个时间序列的值是可取的。

但是对于第二种写入情况而言,四个时间序列的对齐程度低,每个时间序列只在部分时间戳上有值,对于这种场景,我们为每个时间序列单独存一个时间戳,那每一列只需要存一个时间戳和一个值,因为不存null值,列的压缩率也会更高。

对于四维这种时间戳完全对齐的场景,我们完全可以采用第一种存储方式。


收益与代价分析

Vector类型序列的Tsfile文件结构图

假设一个Vector包含m

收益:

  1. flush时,会少(m - 1)列时间戳的encoding以及序列化时间
  2. 查询时,少从磁盘上反序列化(m - 1)列时间戳,在内存中按时间戳对齐时,按照这种方式,数据从磁盘上读取出来的时候,就已经按照时间戳对齐好了,所以少了这一步耗时。
  3. 一个Vector内的所有序列,在磁盘上是连续的,原来的存储方式,一个Vector内的不同sensor序列化到磁盘上时,有可能会被其他序列给分隔开,导致在磁盘上并不是连续存储的,而一个Vector内的序列通常会被一起查询,这种存储方式也会一定程度上减少磁盘的seek次数。理想情况下,如果Vector内的m列一起查询,这种存储方式可以减少(m - 1)次磁盘seek操作。

代价:

  1. 每一列需要维护多维护一个bitmap,假设每列有n行,则在磁盘上需要多占用m * (4 + [n/8])bytes
  2. 文件元数据方面,每一个Vector类型会多占用一个时间戳列的TimeSeriesMetadata以及一个ChunkMetadataList,假设一个tsfile文件中就存储一种Vector类型的序列,默认配置下,文件flush两次关一次,则元数据会多占用(40 + 2 * 40) bytes,一个TimeSeriesMetadata大小约为40B,两个ChunkMetadata大小约为80B
  3. 单独查询Vector中的某些序列子集时,相较于原来的实现,可能会多反序列化一个ZSTree的叶子结点,读取数据时(Chunk),因为Time列和value列物理上不连续,所以会多一次磁盘seek


实验对比


27个sensor,前15个为INT64类型,后12个为DOUBLE类型,时间戳完全对齐,mastervector分支对比


tsfile size

sort

encoding

io

flush total

master

279MB

2ms

8,528ms

1,599ms

8,697ms

vector

212MB

0ms

4,478ms

1,157ms

6,205ms

  • No labels

1 Comment

  1. 收益和代价是否有实验在实测中证实了?换句话说,最后的测试结果数据,是否和前面收益分析吻合?