本文由“大数据治理的理论与技术”专题特约编辑杜小勇教授、杨晓春教授和童咏昕教授推荐.
时间序列数据在能源、制造、金融、气候等领域有着广泛应用, 聚合查询是相关分析场景中常见的查询需求, 快速获取海量数据的概要信息, 对于提高数据分析工作的效率具有重要意义. 通过存储元数据加速聚合查询是一种有效的提升聚合查询执行效率的手段, 但现有的时间序列数据库都使用时间窗口切分数据, 需要对数据进行实时排序和分区, 难以适应物联网场景下高并发、大吞吐量的数据写入特点. 因此, 提出了一种面向聚合查询的Apache IoTDB物理元数据管理方案. 该方案按照数据文件的物理存储特性切分数据, 并结合同步计算和异步计算策略, 优先保证数据的写入性能. 针对时间序列数据中普遍存在的乱序数据, 将时间范围重叠的一组文件抽象为乱序文件组并提供元数据, 聚合查询会被重写为3个结合物理元数据和原始数据的子查询高效执行. 多个数据集上的实验验证了该方案对聚合查询执行效率的提升效果以及不同计算策略对性能的影响.
Timeseries data is widely used in energy, manufacturing, finance, climate and many other fields. Aggregate queries are quite common in timeseries data analysis scenarios to quickly obtain summary of massive data. It is an effective way to accelerating aggregate queries by storing metadata. However, most existing timeseries databases slice data with fixed time windows, which requires real-time sorting and partitioning. In IoT applications with high writing concurrency and throughput, these additional costs are unacceptable. This study proposes a physical metadata management solution in Apache IoTDB for accelerating aggregate queries, in which data are sliced according to the physical storage sharding of files. Both synchronous and asynchronous computing are adopted to ensure writing performance ahead of queries. Out-of-order data streams are another major challenge in IoTDB applications. This study abstracts files with overlapping time ranges into out-of-order file groups and provides metadata for each group. Then aggregate queries will be rewritten into three sub-queries and efficiently executed on physical metadata and timeseries data. Experiments on various datasets have shown the improvement in performance of aggregate queries with the proposed solution, as well as the validity of different computing strategies.
时间序列数据是某些指标或物理量随时间变化的采样值所组成的数据序列, 在能源、制造、金融、气候等领域有着广泛应用. 时间序列数据反映了相应指标在每一采样时间点的测量值, 随着物联网技术的蓬勃发展和应用场景的不断扩展, 各种设备和物品的实时数据通过网络共享, 并被用于监测运行状态、触发事件响应等, 数据中心收集到的海量历史数据被用于分析长周期的变化规律和发展趋势. 在时间序列数据的分析需求中, 聚合查询是常见的快速获取概要信息的手段, 如生产车间的报表中的产能、合格率等信息依赖于对生产和质量检测数据的求和汇总; 气象分析中历史同期的气温、降雨量等数据通常包含对历史数据求取平均值、最大最小值等操作; 数据中心服务器的使用状况看板需要对一段时间内各节点的负载情况求取平均值等. 数值型数据的最大最小值、总和、计数和平均值等聚合查询被广泛用于刻画数据的总体情况, 其查询性能的提升也有助于提高数据分析工作的效率.
聚合查询的加速手段在数据库领域有着广泛的研究[
并行计算加速手段着眼于在聚合查询执行时对数据进行切分, 通过在各个分片之间并行计算, 充分发挥计算性能, 从而提升执行效率. PostgreSQL的内置和自定义聚合查询函数、Spark的自定义聚合函数和累加器均使用了类似的架构, 聚合查询将在各个集群节点之间、节点内部多个线程之间并行执行, 并逐层汇总至主节点完成计算, 它们的衍生产品[
现有的时间序列数据上使用元数据加速聚合查询的方法主要基于固定的时间窗口切分数据并预计算元数据, 其优势是元数据的检索和使用方法较为简单, 例如按天切分时间序列数据, 对某一自然月或自然年的数据执行的聚合查询只需检索相应天的元数据. 但是逻辑上的时间窗口依赖于数据的有序性, 而时间序列数据库的应用场景大多具有高并发、乱序到达的特点, 维持短期数据的有序性所需要的成本往往是不可接受的. 比如在车联网系统中, 车载传感器可以达到数百个, 对网络传输的质量要求较高, 而使用移动网络传输很容易受到网络状况影响, 城市中上下班通勤时段路上行驶车辆猛增, 大量数据并发高速写入数据库, 但同时, 车辆集中容易造成网络拥堵, 数据传输时断时续, 延迟达到的数据在维持有序性时需要频繁重写短期数据文件, 相应地, 基于时间窗口的预计算元数据也需要频繁更新.
基于数据库系统中数据的物理分片切分数据能够有效地解决以上问题. 数据库系统通常会对写入的数据进行物理分片, 划分为数据页或文件, 便于索引及修改. 通过将元数据关联物理分片, 在检索对应的原始数据时, 查询引擎即可利用数据库对物理分片的索引快速定位, 并且数据库会维持不同分片之间的相对均衡. Apache IoTDB[
针对上述问题, 本文提出了一种面向聚合查询的Apache IoTDB物理元数据管理方案.
面向聚合查询的Apache IoTDB物理元数据管理方案框架图
本文第1节介绍在数据库和数据仓库领域元数据管理的相关工作. 第2节主要介绍理论概念和基础知识. 第3节详细阐释本文提出的面向聚合查询的Apche IoTDB物理元数据管理方案. 第4节通过实验验证所提方案的有效性和主要优势. 最后总结全文.
元数据在各类数据库和数据仓库系统中普遍存在, 主要应用于以下几种场景.
(1) 数据管理. 通过保存数据的逻辑模型、组织结构、数据类型等信息, 数据库能够对保存的数据进行约束和管理;
(2) 查询优化. 许多数据库会对数据进行画像, 记录不同数据的分布特征等统计信息, 以此作为评估查询计划代价的依据, 从而优化查询流程;
(3) 统计查询. 元数据能够直接提供数据的摘要信息, 辅助用户快速了解数据的重要特征, 也能够支持特定的聚合查询, 使得这些查询的效率得到显著提升.
本文主要涉及统计查询这一应用场景, 因此, 本节将主要讨论几种数据库和数据仓库中所用的元数据管理和查询技术, 并说明其使用场景和存在的问题.
得益于关系模型强大的表达力, 许多关系型数据库直接将大部分元数据以系统表的形式存储在数据库中, 如MySQL、PostgreSQL、Oracle、SQLServer等. 概要表是其中一类用于保存与实际数据相关的摘要信息、聚合结果等内容的系统表, 根据对应数据的列数, 又可以分为单列和多列概要表两类[
● 单列概要表记录了关系数据库中某一列数据的一些摘要信息, 通常包括数据类型、约束等逻辑结构信息和互异值数量、空值数量、近似分布直方图等数据摘要信息, 如MySQL[
● 多列概要表是以某些列为基础对目标列进行分组聚合而形成的摘要信息, 可以视为使用GROUP BY子句为数据表创建的物化视图或者物理表[
概要表示例
在关系型数据库和数据仓库的应用中, 多列概要表被证明能够在实际查询中有效地提升查询效率, 收益远高于需要付出的预聚合计算代价和物化视图存储代价[
在飞速发展的物联网应用场景下, 时间序列数据具有大体量、高并发、高吞吐量等特性, 但历史数据的信息密度相对较低, 因此, 聚合查询在时间序列数据分析工作中占有重要地位[
OpenTSDB汇总表示例
● 降采样聚合将时间序列数据按照一定的时间区间长度进行分片, 并在每一个区间内, 使用特定的聚合函数给出汇总结果, 形成含有较少数据点的概要序列[
● 分组聚合则是将多条时间序列数据中同一时间的数据点进行聚合并形成概要序列, 如在分布式集群的实时运行负载监测场景中, 通过对集群中每台服务器的实时负载求平均值, 数据库能够直接保存集群整体的负载情况. 简而言之, 降采样聚合是在时间序列内部沿时间维度进行聚合分析, 而分组聚合是在多条时间序列之间沿不同维度或指标进行聚合分析, 二者均会形成新的概要序列, 对该序列的持久化存储能够提升特定的实际查询性能, 同时, 这两种功能还可以相互协作, 满足更复杂的聚合查询需求, 如根据全市范围内多个气象监测站的气温历史数据, 对每天所有监测站的气温进行平均值汇总, 即可获得全市每天的平均气温.
汇总功能的设计依赖于在时间维度上对时间序列数据进行逻辑分片, 其优势是每个分片都对应具有实际意义的时间范围, 与实际查询的时间筛选条件和汇总查询需求更容易匹配. 但相应地, 由于逻辑上的时间范围与物理上的数据文件没有严格的对应关系, 在分布式环境中, 汇总功能并不能很好地利用集群资源. 如在高并发的时间序列数据采集场景中, 一段时间内的数据可能被分散存储在多个节点中, 因此, 汇总计算需要通过集群通信把数据传输到计算节点. 而基于时间序列数据在集群各个节点中的分布特性进行物理分片, 汇总计算就能在文件存储节点上直接完成[
时间序列数据中, 每一个数据点是由时间戳和其对应的数值组成的二元组, 记为
时间序列数据上的聚合函数是根据一个时间序列分片
常见数值统计的聚合函数的可合并性
聚合函数 | 可合并性公式 |
最大值max | |
最小值min | |
计数 |
|
求和 |
|
平均值 |
|
方差var |
基于可合并性, 我们可以将聚合函数分为Compute-Merge-Finalize这3个计算阶段: 在Compute阶段中, 数据会被分组, 形成一系列数据分片, 并在每一个分片上执行聚合操作, 将其中间结果存储在元数据中; 在Merge阶段中, 这些中间结果将被合并, 得到全量数据对应的查询中间结果; 并在Finalize阶段中转换为最终的聚合查询结果. 以平均值函数为例: 在Compute阶段, 每个分片将被分别计数与求和; 进而在Merge阶段, 分别对计数与总和进行合并; 在Finalize阶段, 使用全局数据的总和除以计数得到聚合函数的输出结果. Compute阶段, 各个分片的计算相互独立, 能够充分利用并行化和分布式策略; 同时, 其计算过程能够预先完成并存储中间结果. 因此, 该模型能够显著提升实际聚合查询的执行效率. 类似的计算模型在PostgreSQL及其衍生的TimeScaleDB、MapReduce和Spark及其衍生产品[
TsFile是一种面向时间序列数据的文件存储格式, 在存储形式、编码压缩和读取查询方面做了许多针对性的优化[
TsFile文件格式示意图
一条时间序列数据在TsFile中被分片组织在若干Chunk中, 每个Chunk仅包含一条序列在一段连续时间窗口内的数据, 通常情况下, 各个Chunk之间时间范围互不重叠且保持有序. Chunk内部包含若干数据存储的基本单元Page, 这些Page之间严格保持数据的有序性, Page内的数据点也按照时间戳有序存储. TsFile文件内数据的有序性有助于在查询数据时快速对Chunk, Page进行筛选, 提升数据检索效率. 除此之外, TsFile内各层级还会在头信息中保存局部数据的摘要信息, 如最大最小值、布隆过滤器等, 在处理与数值相关的筛选条件时, 能够快速跳过不符合条件的部分数据.
在编码压缩方面, TsFile将时间和值分别按列存储, 其中, 时间列使用二阶差分编码, 对物联网场景下周期性采集的传感器数据能够实现极高的压缩率, 值则可以根据实际数据的特征选择合适的编码压缩方法.
为了提升服务器的数据写入性能, IoTDB采用了类似于日志结构合并树(log structured merged tree, LSM-Tree)[
时间序列数据中, 新的数据点写入后首先被存储在内存中的MemTable内, 为了尽可能地提升数据写入性能, 内存中的数据并不会严格保持有序性, 只在面向查询或刷写等使用需求时进行排序. 一段时间内的数据被缓存在内存中, 在完成排序后, 被批量刷写到磁盘上的列式存储文件TsFile. 因此, 每个TsFile文件内部的数据是有序的, 并保存了时间范围索引用于快速检索和筛选数据.
文件之间数据的有序性有助于提高数据访问的效率, 但相应地, 在处理写入顺序与数据时间顺序严重不符的场景时, 需要付出额外的文件重写和排序代价. 因此, IoTDB选择牺牲一定的读取性能, 将数据文件存储划分为有序空间和乱序空间两部分. 有序空间内各个数据文件之间保持有序性, 当新的数据文件与已有文件存在时间范围的重叠时, 新的文件将被转移至乱序空间中, 不再消耗额外的代价进行即时排序和整理. 以车联网应用场景为例, 上下班高峰期路上行驶车辆显著增多, 网络拥堵, 部分车辆的数据就可能出现如
车联网应用场景中的乱序现象和乱序数据文件的产生示意图
IoTDB中的乱序文件和乱序空间的示意图
LSM树中分层合并的机制也被相互隔离地实现在有序空间和乱序空间内, 用于将散碎的小文件收集整理为下一层的大文件, 提升数据检索和访问的效率. 特别地, IoTDB使用跨空间的合并策略来保证数据文件的最终有序性, 即从两个空间中选择存在时间范围重叠的文件, 读取数据进行排序和文件重写. 乱序空间的存在, 使得对应于文件的物理元数据不能简单地进行合并操作, 而必须充分考虑数据文件间的时间范围重叠情况.
数据删除在时间序列数据的应用场景中是相对少用的操作, 通常仅用于纠正部分错误数据或删除过于陈旧的历史数据. 因此, IoTDB采用了懒删除策略以避免数据文件的频繁重写. 删除操作以日志的形式保存在数据文件附带的修改记录文件(modification file)中[
本文所提出的物理元数据管理方案由3个部分组成, 其模块图如
面向聚合查询的Apache IoTDB物理元数据管理框架图
● 物理元数据存储引擎负责元数据的存储和更新, 并提供高效的数据查询和读取接口. 在具体实现中, 我们分别使用了基于数据文件和关系型数据库的两种存储方法.
● 物理元数据预计算引擎负责根据计算和更新物理元数据, 保持与原始数据的一致性, 共包含3种计算策略, 其中, 同步计算策略与IoTDB存储引擎的数据文件操作关联, 在数据变动时, 尽可能地保持物理元数据的一致性; 异步计算策略通过定时任务, 利用闲时资源更新缺失或过时的元数据; 查询时计算策略则将查询执行过程中计算的部分中间结果更新到元数据中. 3种策略相互协作, 在优先保证数据库写入性能的同时, 保证物理元数据与原始数据的最终一致性.
● 物理元数据聚合查询执行器负责回答输入的聚合查询, 原始查询被重写为3个子查询, 通过检索物理元数据合并计算提升执行效率, 并结合原始数据确保结果的正确性.
以下将分别介绍3个模块的设计细节.
存储引擎旨在持久化存储所有预计算的元数据, 为查询引擎提供查询优化支持. 存储引擎的实体关系模型[
存储引擎ER图
FileSeriesStat统计实体与时间序列数据分片一一对应, 存储了分片的时间范围信息和物理元数据, 其中, 时间范围信息包含分片的起始时间和终止时间, 以及是否与其他数据文件中的分片存在时间范围的重叠; 物理元数据保存了5个数值统计量, 用于支持最大最小值、计数、求和、平均值和方差这些聚合函数, 以及完成计算时File实体的版本号, 用于在查询中校验物理元数据与实际数据的一致性.
FileGroupSeriesStat统计实体对应时间范围相互重叠的一组数据文件抽象出的乱序文件组, 与数据分片的一对多关系记录了乱序文件组与该组数据文件中的数据分片的对应关系. 与FileSeriesStat统计实体类似, FileGroupSeriesStat统计实体存储了乱序文件组的起止时间范围和相应的元数据, 其中, 时间范围是该组数据文件时间范围的并集.
在存储引擎的设计中, 为了保证查询的正确性, 两个概要表的记录以及两个统计表中的起止时间戳始终与原始数据保持强一致性, 任何时刻, 其与原始数据文件的信息都是保持一致的. 同时, 为了保证查询的高效性, 两个统计实体中的统计量信息只保证与原始数据的最终一致性, 数据库中的统计信息不一定与实际的数据文件统计信息一致. 聚合查询在使用统计量之前需要先进行统计量版本号的校验, 当统计量的版本号与对应数据文件的版本号不一致时, 需要先解决数据冲突, 更新存储引擎中的元数据后, 再利用统计量进行查询.
基于以上存储模型, 本文实现了基于TsFile文件和基于关系型数据库的两种存储方案.
基于文件的元数据存储方案将元数据与原始数据一同存储在TsFile文件中, 在文件内部的头信息中保存了相应时间序列数据分片的起止时间以及最大值、最小值、计数和总和的统计信息. 在读取数据文件时, 文件头被首先读取, 并用于校验是否满足时间范围和值筛选条件; 随后, 在聚合查询中使用元数据进行合并计算查询结果[
基于文件的物理元数据存储和查询方案虽然能够通过元数据显著提升聚合查询的执行效率, 并在文件格式中具有自解析性, 但也存在明显的不足之处: 物理元数据的结构与TsFile文件格式绑定, 这虽然在减少磁盘I/O、提升读取速度上有一定优势, 却也限制了其自身的更新和功能扩展. 一方面, 由于IoTDB的懒删除策略, 数据文件在发生删除操作时并不会即时修改, 因此, 存储的元数据也无法更新从而不能保持与数据的一致性; 另一方面, TsFile文件格式已经被预先定义, 用户无法在不深入理解和大规模改动源代码的基础上增加新的元数据条目, 以满足不同应用场景的聚合查询需求.
利用预计算的元数据来加速查询过程的关键在于保证元数据与原始数据的一致性, 而关系型数据库的ACID特性很好地弥补了上述方案在保持元数据一致性方面的不足. 同时, 考虑到元数据自身的读写性能, 本文使用轻量级关系型数据库SQLite3实现了基于关系型数据库的元数据存储方案.
元数据与原始数据的分开存储, 使得元数据的更新不再依赖于TsFile文件的改动. SQLite3中, 元数据信息可以在原始数据有变更时进行动态更新, 从而保证了元数据的可用性, 减少了查询过程中由于元数据不可用读取原始数据带来的性能损失. 同时, 关系型数据库和SQL查询语言的特性也增强了元数据信息的可扩展性, 用户只需通过DDL和DML即可向数据库中添加新的元数据条目.
本文在物理元数据预计算引擎中设计了3种计算策略, 在物理元数据的一致性和聚合查询的执行效率之间取得平衡: 同步计算策略在数据文件操作的同时对物理元数据进行更新; 但在计算资源有限的条件下, 部分同步计算任务无法完成会导致物理元数据缺失或过时, 异步计算策略将通过定时任务扫描并更新这些元数据, 更好地利用闲时计算资源提高元数据的可用率; 查询时计算策略则利用执行查询需要的计算资源将中间结果写回存储引擎, 在保证查询效率和结果正确性的同时, 更新缺失或过时的物理元数据, 加速后续涉及相同数据的聚合查询.
在系统实现中, 为了限制物理元数据预计算引擎所用的计算资源, 同步和异步计算策略共享线程池和任务队列. 在数据集中大量写入时, 资源会被占满而无法接收新数据的物理元数据预计算任务, 由此造成的物理元数据缺失或过时问题将由异步计算策略在系统负载低谷时提交计算任务. 查询时计算策略则单独占用查询执行器的计算资源, 当同步和异步计算策略均无法在实际查询到达前完成物理元数据的计算和更新时, 查询时计算策略是对结果正确性的最终保障手段. 物理元数据预计算引擎能够在系统后台自动地完成资源的分配和3种计算策略之间的协调, 通常只需由数据库管理员根据实际情况设定引擎所能使用的资源上限, 或在确有必要时手动提交某些时间序列的物理元数据异步计算任务, 而用户在写入和查询时可以做到几乎无感.
同步计算策略旨在实时保持物理元数据与实际数据的一致性, 因此需要在数据文件发生变动时即时触发计算任务. IoTDB中共有3类数据文件操作, 如
同步计算策略功能模块图
● 文件刷写操作发生时, 对应的数据仍然驻留在内存中, 预计算引擎将基于内存中的数据完成物理元数据的计算, 通过对数据按照时间进行排序, 时间序列数据分片的起止时间能够被直接获取, 而5项数值统计信息则可以使用流式算法在对数据的一次遍历中求出. 预计算引擎将对一份数据文件中包含的多条时间序列分别计算, 并将其物理元数据写入到存储引擎中.
● 由于物理元数据中含有与数值有关的统计信息, 因此在数据删除操作中, 同步计算模块必须重新读取对应的数据文件, 检索实际被删除的数据点, 并更新物理元数据. 其中, 计数、总和及平方和这3项具有增量更新的特性, 即只需从数值中减去被删除数据点的对应贡献即可完成更新, 因此在更新过程中, 模块并不需要完全扫描数据文件, 而是借助区块、页的索引快速定位到被删除数据所在位置, 仅读取对应的数据点, 对物理元数据进行增量更新. 最大值和最小值不具备以上特性, 尽管在被删除数据中不含最大值和最小值时不需要更新, 但在其他情况下, 均需要重新读取未被删除的数据点进行计算.
● 物理元数据的各项统计信息具有可合并性, 因此, 多个数据文件合并时通常其元数据也可直接合并, 不需要读取任何原始数据即可完成增量更新. 但受限于IoTDB对乱序文件的管理机制, 当待合并文件中存在乱序文件时, 其多份文件之间可能存在数据冲突, 因此无法直接合并其物理元数据, 而必须在读取所有数据消除冲突完成合并后, 根据新的文件重新计算.
同步计算策略牺牲了一定的数据写入和修改性能, 以换取物理元数据的一致性和可用率的最大化. 但在写入压力极大的场景下, 预计算引擎挤占计算资源可能阻塞写入线程池, 甚至导致系统崩溃. 异步计算策略则通过限制计算物理元数据所占用的资源, 降低对写入性能的负面影响, 并使用周期性扫描和更新来维持物理元数据和实际数据的最终一致性. 定时任务首先从存储引擎中获取版本号与数据文件不一致的元数据条目, 并按照对应的文件进行分组, 使用的SQL语句如下.
随后, 对每一份文件的物理元数据更新过程将分别创建计算任务. 各任务之间相互独立, 因此能够在线程池中并行执行; 或在集群环境中利用分布式计算资源, 快速完成批量数据文件的物理元数据计算任务.
异步计算策略使用数据文件和对应修改记录文件的字节数作为版本号, 以此发现数据删除和文件合并带来的数据变更. 在同一份数据文件上的修改仅涉及2份文件的追加写入操作, 因此, 字节数作为版本号能够有效地检测原始数据的变更. 不同于同步计算策略的触发器模式, 异步计算策略无法获取数据变更的原因, 如具体删除的数据范围、被合并的原始文件等信息, 因此必须通过读取最新的数据文件重新计算物理元数据.
查询时计算策略旨在更新查询过程中涉及的与原始数据不一致的元数据信息. 对于查询所涉及的数据文件, 查询引擎使用SQL语句检索所有满足查询条件且元数据版本与文件版本不一致的数据文件, 并交由预计算引擎进行计算和更新. 查询时计算策略既保证了在当前查询执行时物理元数据表中所有条目均与数据文件保持一致, 降低了查询重写的难度, 又有助于提升后续涉及相关文件的聚合查询的执行效率.
乱序文件组涉及多份时间范围前后重叠的乱序文件, 组内可能含有未被当前查询所覆盖的数据, 比如在
结合存储引擎中已有的元数据条目, 查询执行器能够将特定的聚合查询重写为结合元数据和原始数据的查询, 充分利用预计算的结果加速查询效率. 聚合查询的执行流程如
物理元数据聚合查询匹配和执行流程图
在查询实际执行过程中, 理想情况下, 查询执行器只需从物理元数据表中查找符合序列和时间范围条件的元数据条目, 进行合并和计算就能获取最终的聚合查询结果. 但是IoTDB中乱序文件的存在, 使得对应的物理元数据无法直接使用, 因此执行器根据数据文件的有序性和元数据信息将中间结果分为3部分: (1) 从乱序文件组的元数据表
以下将以查询北京市某路口一天内通过的车辆总数的聚合查询为例, 分别阐明3个子查询的重写原理及在样例查询上的重写结果. 该查询所涉及的数据文件及其覆盖的时间范围如
查询所涉及的数据文件及其时间范围示意图
乱序文件组表示数据时间范围相互存在交集的一组乱序文件, 比如
乱序文件组的元数据仅在查询时计算策略中进行更新, 从未被历史查询完全覆盖的乱序文件组存在元数据缺失问题, 比如TsFile9-11, 因此, 即使排除掉在乱序文件组元数据子查询中已匹配到乱序文件组的数据文件, 其余文件之间仍然可能存在时间范围的重叠, 查询执行器必须对其有序性进行辨别. 有序文件之间不存在数据冲突, 其物理元数据可以直接合并, 但是查询语句时间筛选条件边界附近的文件可能含有不符合筛选条件的数据, 比如
有序文件物理元数据子查询的SQL语句如下.
特别地, 含有不符合筛选条件的数据文件, 其
其他乱序文件及被时间筛选条件切分的数据文件需要重新读取原始数据完成计算, 这一子查询将被重写为IoTDB上的聚合查询, 其时间筛选条件为所需文件的时间范围的并集, 如TsFile9-12对应数据的时间范围应为16:00-24:00. 乱序文件组时间范围的重叠区间合并问题可以使用排序和遍历操作解决, 将所有数据文件按照起始时间正序排列, 则重叠现象仅发生在相邻的时间范围之间, 亦即同一乱序文件组中的文件一定相邻且连续排列. 对所有文件按顺序遍历, 当前文件乱序但上一份文件有序说明一个乱序文件组的第1份文件被发现; 反之, 当前文件有序但上一份文件乱序说明当前乱序文件组的文件已被完全发现. 合并后, 时间范围的起始时间为第1份文件的起始时间, 终止时间为最后一份乱序文件的终止时间. 查询执行器利用合并后的时间范围, 即可生成对应原始数据聚合子查询的时间范围筛选条件.
以上重叠区间合并问题的算法可以通过SQL中的窗口函数和GROUP BY功能实现, 对所有选中的文件按照起始时间和终止时间排序后, 使用窗口函数访问前一行并判断
图 11中文件利用SQL合并重叠时间范围的中间结果
文件序号 | |||
TsFile1 | false | 1 | 1 |
TsFile2 | false | 0 | 1 |
TsFile3 | false | 0 | 1 |
TsFile7 | false | 0 | 1 |
TsFile8 | false | 0 | 1 |
TsFile9 | true | 1 | 2 |
TsFile10 | true | 0 | 2 |
TsFile11 | true | 0 | 2 |
TsFile12 | true | 0 | 2 |
在以上中间结果中, 乱序文件组的一组文件
max(min(
min(max(
我们在4个数据集上验证所提方案的有效性.
实验数据集基本信息
名称 | 行数 | 列数 | 非空数据点数 |
HAR | 16 603 407 | 6 | 49 500 000 |
中船 | 2 046 175 | 17 | 54 500 000 |
中车 | 416 049 | 4 065 | 1 340 500 000 |
Gaussian | − | − | 2 000 000 000 |
本文使用Apache IoTDB 0.13.0版本作为实验平台, 在查询性能实验中, 本文还使用了另外两款时间序列数据库InfluxDB 2.2.0和TimescaleDB 2.7.2作为对比, 其中, InfluxDB是一款使用Go语言编写的高性能时间序列数据库, 其内置的聚合函数采用流式算法实现; TimescaleDB是一款基于关系型数据库PostgreSQL的时间序列数据插件, 根据时间序列数据的特性对存储和查询进行了改造和优化, 其聚合函数在执行过程中使用了PostgreSQL本身的并行计算加速手段, 插件提供的高级功能持续查询则通过生成物化视图实现了汇总查询, 能够进一步提升大规模数据的聚合查询执行效率. 所有数据库均部署在一台CPU为Intel(R) Core(TM) i7-9700 CPU@3.00 GHz、内存16 GB的台式机上, 所有文件存储在一块5 400转/分钟的机械硬盘上.
本文主要测试了最大值MAX和均值AVG这两个聚合函数在不同实现方案、不同数据库之间的性能差异, 两者分别属于单列和多列元数据聚合查询, 并已在测试基准中广泛使用[
实验所用的查询语句为仅包含时间范围筛选条件的单个聚合查询, 在固定查询数据点个数的情况下, 时间范围的起始时间在有效范围内随机选取, 以避免数据库的查询缓存机制影响实验结果. 而随机数的步长为固定批量的数据, 这与实际应用中按照日历天数选取起止范围的查询需求相符, 比如在车联网数据分析和可视化场景中, 数据看板通常以自然日或自然月为参考范围分析某辆车的行驶数据, 即时间范围总是倾向于从某天0时开始, 而随机选取其他时间作为起始时间的查询需求相对较少. 在IoTDB中查询语句的模板如下.
同步计算策略会保证在数据写入的同时完成物理元数据的计算和存储, 以在最大程度上提升聚合查询的执行效率. 因此, 本实验测试了在所有物理元数据均可用的前提下, 聚合查询性能与查询涉及的数据量之间的关系. 实验结果如
数据量对查询性能的影响
横向对比两种不同的实现方案, 基于文件的存储方案在查询数据量小于4E8时平均比基于关系型数据库的存储方案性能提升约37%; 随着查询数据量增长至7E8以上, 两者查询性能基本一致. 这是因为使用关系型数据库时需要额外引入连接、SQL解析等耗时因素, 数据库内索引和连续读取的优势在数据量较小时无法弥补这一缺陷; 而数据量持续增长时, 访问大量数据文件的文件头带来的磁盘寻道和读取的压力将成为基于文件的存储方案的性能瓶颈, 关系型数据库在数据访问方面的优势使得二者的性能差异逐渐缩小至10%以内.
内存数据刷写至磁盘时, 元数据的同步计算在带来查询性能提升的同时, 也提高了数据的磁盘写入代价. 本实验测量了基于关系型数据库的元数据存储方案在不同数据量下, 元数据预计算时间与文件I/O读写时间在内存数据写入磁盘时的占比, 结果如
同步计算对数据写入性能的影响
在数据量较小时, 与数据刷写至磁盘的I/O开销相比, 元数据统计信息的计算以及SQLite3数据库写入开销较小, 元数据的预计算在整体写入耗时中占据约10%−20%. 数据量增大后, 随着元数据计算开销和数据库写入开销的增大, 预计算时间占比逐渐增加至50%−60%. 这说明在数据写入磁盘时, 利用同步计算策略更新元数据的方案带来的磁盘写入代价是不可忽视的; 且在大数据量下, 对写入性能的影响更为明显. 同时, 也印证了利用异步计算策略和查询时计算策略更新元数据的必要性.
当TsFile涉及文件有修改时, 基于文件的元数据存储方案由于元数据无法及时同步, 在之后的聚合查询中, 需要重新读取数据文件并计算相关统计信息. 而基于关系型数据库的元数据存储方案则会利用同步计算策略对元数据进行更新, 从而保持元数据与原始数据的一致性. 为了比较两种方案及UDF方案在原始数据有删除时的查询性能, 本实验在4个原始数据集的基础上, 分别随机挑选了一定比例的TsFile文件, 随机删除其中10%的时间序列数据并测试查询性能, 实验结果如
删除涉及文件比例对查询性能的影响
实验结果表明, 本文实现的两种元数据管理方案在数据有删除时均能有效地提高查询效率, 性能与UDF方案相比提高了3−4个数量级. 随着数据删除涉及的TsFile文件比例的增加, UDF方案由于需要在查询时读取全部数据并计算统计信息, 其查询用时与删除涉及文件比例无明显变化.
基于文件的元数据存储方案在删除涉及文件比例从0增长至10%时, 查询性能显著下降约2个数量级; 随后, 查询性能随删除涉及文件比例的增长呈现近似线性下降. 这是由于在数据没有删除记录时, 基于文件的存储方案在进行聚合查询时可以直接读取预计算的元数据返回查询结果; 而当数据有删除时, 由于其元数据无法及时同步, 对于有删除记录的数据文件, 该方案需要重新读取原始数据进行计算, 因此查询性能与没有删除记录时相比会有突变. 随后, 当删除记录继续增多时, 其查询用时会随删除涉及文件比例近似线性增长.
基于关系型数据库的存储方案在数据删除时会同步更新元数据, 在查询过程中无须读取原始数据, 因此查询用时随删除记录的增多并无明显变化. 其查询性能在数据无删除记录时与基于文件的存储方案相当, 且随着删除涉及文件比例的增大, 前者性能比后者提高了2-4个数量级.
异步计算的优势在于, 能够在不影响数据写入和查询性能的前提下定期更新元数据.
异步计算比例对查询性能的影响
在可用元数据信息较少时, 大部分查询都需要读取原始数据文件, 查询用时较长, HAR和中船数据集中的查询用时达到了3.5 s左右; 而在中车数据集及Gaussian数据集中, 由于数据量较大, 查询用时更是达到了45 s左右. 随着元数据可用的TsFile文件占比越高, 聚合查询能够利用的元数据信息越多, 因此查询效率也越高, 查询用时随可用元数据比例的增加呈现近似线性下降. 当可用元数据比例达到100%时, 查询用时与第4.2.1节中同等数据量下的实验结果相近, 收敛至10 ms以内.
查询时计算策略能够利用查询中间结果反哺物理元数据存储, 加速后续涉及相同数据的聚合查询. 为了验证策略的有效性, 本实验在禁用了同步计算和异步计算策略的情况下, 从关系型数据库中删除所有已存储的物理元数据, 在数据集上随机生成一组各自覆盖约1/20数据的聚合查询, 仅使用查询时计算策略更新所涉及数据文件对应的物理元数据,
查询时计算对查询性能的影响
由于每次聚合查询是从整个数据集中随机选取了一段固定长度的时间范围, 涉及的数据文件是否被此前的聚合查询所覆盖也是随机的, 因此查询用时呈现出剧烈的不稳定, 但整体上仍表现出明显的下降趋势. 查询ID小于40的查询在执行时, 存储引擎中已被查询时计算策略更新的物理元数据有限, 随机选取的时间范围较难命中已有条目, 查询用时较长, 中车和Gaussian数据集上的用时与
聚合查询在时间序列数据的分析场景中有着广泛应用, 使用元数据加速聚合查询能够显著提升执行效率. 本文提出了一种面向聚合查询的Apache IoTDB物理元数据管理方案, 针对时间序列数据采集和存储场景中写入负载高、计算资源有限以及数据在时间维度上分布不均匀、非有序等问题, 本文提出了基于数据库中数据文件管理机制切分数据的物理元数据方案, 并结合同步计算、异步计算和查询时计算策略, 降低对数据写入性能的影响, 维持元数据的最终一致性. 本文使用关系模型对物理元数据进行建模, 将时间序列数据上的聚合查询重写为物理元数据表上的聚合查询语句和读取部分原始数据的子查询, 多个数据集上的查询实验证明了本文所提出方案对聚合查询执行效率的提升效果和多种计算策略的有效性.
在本文工作的基础上, 许多方向仍然值得进一步研究: 首先是目前同步计算策略在文件刷写阶段仍然会对写入性能产生一定的负面影响, 通过流水线作业、并行计算等方法能够避免直接阻塞刷写线程, 但仍然局限于单台计算机的可用资源, 实际生产环境往往部署在集群中, 数据存储节点和计算节点也可能不同, 利用分布式架构或许能够进一步减轻数据写入阶段的压力; 另外, 本文仍然只涉及最大最小值、计数、求和、平均值、方差等常见的数值统计函数, 但与已有工作相比, 本文所用的聚合函数模型和存储的ER模型具有良好的可扩展性, 后续应进一步探索支持更多聚合函数乃至用户自定义聚合函数, 以满足实际数据分析场景中多样的聚合查询需求.
Huang XD, Zheng LF, Qiu MM,
黄向东, 郑亮帆, 邱明明, 等. 支持时序数据聚合函数的索引. 清华大学学报: 自然科学版, 2016, 56(3): 229−236, 245.
Jensen SK, Pedersen TB, Thomsen C. Modelardb: Modular model-based time series management with spark and Cassandra. Proc. of the VLDB Endowment, 2018, 11(11): 1688−1701.
Wang D. Research on Summary query based on database [Ph. D. Thesis]. Shenyang: Northeastern University, 2013 (in Chinese).
王丹. 基于数据库的Summary查询研究[博士学位论文]. 沈阳: 东北大学, 2013.
Sheng J, Fang J, Guo XQ, Wang CD. Implementation of multidimensional aggregate query service for time series data. Journal of Chongqing University, 2020, 43(7): 121−128 (in Chinese with English abstract).
盛家, 房俊, 郭晓乾, 等. 时序数据多维聚合查询服务的实现. 重庆大学学报, 2020, 43(7): 121−128.
Wang C, Huang X, Qiao J,
Naumann F. Data profiling revisited. ACM SIGMOD Record, 2014, 42(4): 40−49.
Widenius M, Axmark D, Arno K. MySQL Reference Manual: Documentation from the Source. O'Reilly Media, Inc., 2002.
Momjian B. PostgreSQL: Introduction and Concepts. New York: Addison-Wesley, 2001.
Mannino MV, Chu P, Sager T. Statistical profile estimation in database systems. ACM Computing Surveys (CSUR), 1988, 20(3): 191−221.
Poosala V, Haas PJ, Ioannidis YE,
Czejdo B, Taylor M, Putonti C. Model of summary tables selection for data warehouses. In: Proc. of the Int'l Conf. on Advances in Information Systems. Berlin, Heidelberg: Springer, 2000. 1−13.
Zhang Q. Research on key technology of materialized view based on aggregation function [Ph. D. Thesis]. Nanjing: Nanjing University of Science and Technology, 2010 (in Chinese).
张茜. 基于聚合函数的物化视图关键技术的研究[博士学位论文]. 南京: 南京理工大学, 2010.
Teschke M, Ulbrich A. Using materialized views to speed up data warehousing. Technical Report, IMMD 6, University of Erlangen-Nuremberg, 1997.
Gutiérrez AG. Applying OLAP pre-aggregation techniques to speed up aggregate query processing in array databases [Ph. D. Thesis]. IRC-Library, Information Resource Center der Jacobs University Bremen, 2012.
Gutiérrez AG, Baumann P. Computing aggregate queries in raster image databases using pre-aggregated data. In: Proc. of the ICCSA. 2008. 447−479.
Timko I, Dyreson CE, Pedersen TB. Pre-aggregation with probability distributions. In: Proc. of the 9th ACM Int'l Workshop on Data Warehousing and OLAP. 2006. 35−42.
Edara P, Pasumansky M. Big metadata: When metadata is big data. Proc. of the VLDB Endowment, 2021, 14(12): 3083−3095.
Babu S, Widom J. Continuous queries over data streams. ACM Sigmod Record, 2001, 30(3): 109−120.
Larsen C, Sigoure B, Ligus O,
Hawkins B, Sabin J, Nicolaie A,
Klemm S, Nordström E, Arye M,
Pelkonen T, Franklin S, Teller J,
Kornacker M, Behm A, Bittorf V,
Choi H, Lee KY. Efficient processing of an aggregate query stream in MapReduce. KIPS Trans. on Software and Data Engineering, 2014, 3(2): 73−80.
Peng D, Duan K, Xie L. Improving the performance of aggregate queries with cached tuples in MapReduce. Int'l Journal of Database Theory and Application, 2013, 6(1): 13−24.
O'Neil P, Cheng E, Gawlick D,
Chen PPS. The entity-relationship model—Toward a unified view of data. ACM Trans. on Database Systems (TODS), 1976, 1(1): 9−36.
Huang XD, Wang JM, Wong R,
Qiao JL, Huang XD, Wang JM,
Stisen A, Blunck H, Bhattacharya S,
Mostafa J, Wehbi S, Chilingaryan S,
Liu R, Yuan J. Benchmarking time series databases with IoTDB-benchmark for IoT scenarios. arXiv: 1901.08304, 2019.