- 本次笔记记录对TsFile的写入功能的学习,TsFile层面的类是TsFileWriter,用户通过该类提供的接口完成数据的写入
-
注册时序,录入元数据
- 在TsFileWriter中,每个设备device都对应一个MeasurementSchemaGroup,记录了该设备下每个传感器的时序元数据,用户在写入数据之前,需要先调用TsFileWriter的register_timeseries()函数将时间序列的设备名、传感器名、数据类型、编码类型、压缩类型保存到schema_中。
-
写入数据
- 数据的写入会主要用到TsFileWriter、ChunkWriter和PageWriter这三个类。
- 流程
- TsFileWriter写入数据
- 写入方式
- TsRecord方式:TsRecord指的是时间序列数据库中存储的时间序列数据记录。时间序列是一系列按时间顺序排列的数据点,通常用于表示随时间变化的指标或度量值,比如气温、股价、传感器数据等。TsRecord包含了时间戳和对应的数值,以及可能的其他附加信息,用于描述某一时刻或时间段内的具体数值。
- 调用do_check_schema()函数,检查要写入的TsRecord对象的元数据是否符合之前注册的元数据。(目前只是检查名字是否存在,而不检查数据类型是否正确。)不过它同时会对chunk_writer进行初始化。(每次write都会先check)
- 一个Record对象可能包含同一时间戳下的多个measurement,在do_check_schema()函数的执行过程中,还会为每个measurement创建各自的chunk_writer并初始化。
- 遍历每个measurement,使用对应的chunk_writer将时间戳和它的value写入(调用write_point()函数,内部又调用ChunkWriter的write()函数)。
- measurement:在时间序列数据库中,测量是指对某个特定事物或现象进行观测或采集的数据。可以将测量理解为在一段时间内对某个特定指标或变量进行的连续观测所得到的数据序列。比如,气温、湿度、电流、压力等都可以是测量的对象,其对应的数据序列就是测量数据。在某些时间序列数据库中,测量还可以包括有关数据的元信息,比如测量的单位、描述等。
- Tablet方式:Tablet是数据库系统中的一个概念,通常用于表示数据的逻辑组织单元。在一些数据库系统中,特别是分布式数据库或列式存储的数据库中,数据被组织成不同的Tablet,每个Tablet负责存储和处理一部分数据。Tablet可以看作是数据的分片,有助于提高数据库的并发处理能力和扩展性。
- 调用do_check_schema()函数,检查要写入的Tablet对象的元数据是否符合之前注册的元数据。不过它同时会对chunk_writer进行初始化。(每次write都会先check)
- 一个Tablet对象包含同一时间戳下的多个measurement,在do_check_schema()函数的执行过程中,还会为每个measurement创建各自的chunk_writer并初始化。
- 遍历每个measurement,使用对应的chunk_writer将该列物理量对应的时间戳数组和value数组写入(调用write_column()函数)
- 循环检测bitmap的每行是否为空,若不为空就使用ChunkWriter的write()函数写入一个point。
- TsRecord方式:TsRecord指的是时间序列数据库中存储的时间序列数据记录。时间序列是一系列按时间顺序排列的数据点,通常用于表示随时间变化的指标或度量值,比如气温、股价、传感器数据等。TsRecord包含了时间戳和对应的数值,以及可能的其他附加信息,用于描述某一时刻或时间段内的具体数值。
- 写入方式
- ChunkWriter写入k-v键值对
- 识别value的数据类型并检查是否与元数据一致。
- 调用PageWriter的write()函数将键值对写入。
- 检查当前Page是否写满了,如果是的,就执行d。
- 将当前PageWriter的statistic合并到ChunkWriter的statistic,然后调用PageWriter的write_to_chunk()函数,将这批数据先封装成一页PageData(同时进行压缩),依次把PageHeader、PageData写入Chunk里面。
- PageWriter写入k-v键值对
- 识别value的数据类型并检查是否与元数据一致。
- 对timestamp编码,写入time_out_stream_;对value编码,写入value_out_stream_;然后更新statistic。
- TsFileWriter写入数据
-
数据刷盘
- 目的:在写入过程中,TsFile的部分数据可能会暂存在内存中。当写入缓冲区已满或达到一定条件时,为了持久化数据,需要进行刷盘操作,将缓存中的数据写入磁盘。在计算机组成原理也曾学习过类似的概念。
- 数据的刷盘会主要用到TsFileWriter、TsFileIOWriter和write_file_这三个类。
- 数据刷盘并不是真的刷到磁盘,而是通过linux的write()系统调用,将数据刷到操作系统的缓存中。
- TsFileWriter执行flush()
- TsFileIOWriter执行start_file()
- TsFileIOWriter执行start_flush_chunk_group()
- TsFileWriter执行flush_chunk_group()
- TsFileIOWriter执行end_flush_chunk_group()
-
结束写入
- 当所有的时间序列数据都被写入到Tsfile文件中后,需要进行结束写入操作。
- 结束写入主要用到TsFileWriter、TsFileIOWriter和write_file_这三个类。
- 根据内存中缓存的元数据,生成TsFileMetadata并追加到文件尾部,最后关闭文件。
-
建立索引
- 生成TsFileMetadata的过程中比较重要的一步是建立元数据索引 (MetadataIndex) 树。元数据索引采用树形结构进行设计的目的是在设备数或者传感器数量过大时,可以不用一次读取所有的TimeseriesIndex,只需要根据所读取的传感器定位对应的节点,从而减少 I/O,加快查询速度。
- 索引树的样子:索引树本身也是拆成两部分,每个device的所有measurement的chunk构成一个索引树,然后所有设备构成一个索引树,其中设备索引树的叶子节点指向该叶子对应的设备的measurement索引树的树根。
- 在前面写数据部分的时候,已经记录了每个chunk的基本信息,这个信息记录在chunk_group_meta_list_ 里面,它是两层Map(std::map,key有序),第一层是设备,第二层是该设备内的测点,大致的样子如图:
- TSMIterator 这个类是用来迭代chunk_group_meta_list_的辅助类,如图中红色箭头所示,迭代会顺序遍历每一个chunk,然后将每个物理量的ChunkMeta收集到一起,整理成TimeseriesIndex。
-
心得体会
- 在学习完TsFile的文件结构之后,我清楚了chunk,page等概念,再学习写入就会相对轻松一些。这短时间的学习我了解到Tsfile是一种面向时序数据定义的一种文件格式,其提供了一套将时序数据转换为字节的规则,在减少磁盘占用的前提下,有效地提升了数据查询分析的效率,能够为上层应用提供良好的数据存储和查询支持。它的目标场景是管理一个或多个设备的时序数据,写入原理则是基于列式存储的设计思想,通过数据分段、压缩编码和索引等技术来提高存储效率和查询性能。
- 写入过程又涉及到了许多新的类和函数和一些新的数据库概念,特别是数据刷盘部分的流程细节我查阅了许多资料去试图理解,但还是没能成功,只好先简略记下流程。在天谋科技的实习期也临近结束了,如果之后还有机会与IoTDB打交道,希望能有机会进一步学习,十分荣幸能接触到清华大学的优秀同学们共同努力开发的前沿数据库技术。
文章来源地址https://www.toymoban.com/news/detail-832112.html
文章来源:https://www.toymoban.com/news/detail-832112.html
到了这里,关于IoTDB使用学习笔记(四)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!