用于超大时间序列的最佳索引数据结构

Best of breed indexing data structures for Extremely Large time-series

本文关键字:最佳 索引 数据结构 时间序列 用于      更新时间:2023-10-16

我想向其他SO征求他们对用于索引时间序列的最佳数据结构(也称为列数据,也称为平面线性数据)的意见。

基于采样/离散化特性,存在两种基本类型的时间序列:

  1. 规则离散化(每个样本都用一个共同的频率采集)

  2. 不规则离散化(在任意时间点取样)

需要的查询:

  1. 时间范围[t0,t1]中的所有值

  2. 时间范围[t0,t1]中大于/小于v0 的所有值

  3. 时间范围[t0,t1]中的值范围[v0,v1]中的所有值

数据集包括汇总时间序列(有点超过不规则离散化)和多元时间序列。所讨论的数据集大小约为15-20TB,因此处理是以分布式方式执行的,因为上面描述的一些查询将导致数据集大于任何一个系统上可用的物理内存量。

在这种情况下,分布式处理还意味着将所需的特定于数据的计算与时间序列查询一起调度,以便计算可以尽可能靠近数据进行,从而减少节点间的通信(有点类似于映射/减少范式),这在计算和数据的短距离内是非常关键的。

该指数应该能够应对的另一个问题是,绝大多数数据是静态/历史数据(99.999…%),但每天都会添加新数据,想想"现场传感器"或"市场数据"。其理念/要求是能够以尽可能低的延迟更新任何正在运行的计算(平均值、garch等),其中一些正在运行的运算需要历史数据,其中一些将超过可以合理缓存的数据。

我已经考虑过HDF5,它对较小的数据集运行良好/高效,但随着数据集变得更大,它开始拖动,而且前端没有本地并行处理功能。

寻找建议、链接、进一步阅读等(C或C++解决方案、库)

您可能想要使用某种类型的大型平衡树。正如托比亚斯提到的,B-树将是解决第一个问题的标准选择。如果你也关心快速插入和更新,那么麻省理工学院和CMU等地正在为这些新的"缓存遗忘B树"做很多新的工作。关于这些东西的实现的一些讨论,请查阅Tokutek DB,他们有很多很好的演示,如下所示:

http://tokutek.com/downloads/mysqluc-2010-fractal-trees.pdf

问题2和3通常要困难得多,因为它们涉及更高维度的范围搜索。实现这一点的标准数据结构是范围树(它给出O(log^{d-1}(n))的查询时间,代价是O(nlog^d(n)的存储)。通常情况下,不会想要使用k-d树来进行类似的操作。虽然kd树确实具有最优的O(n)存储成本,但事实上,如果只使用0(n)存储器,则无法以比O(n^{(d-1)/d})更快的速度评估范围查询。对于d=2,这将是O(sqrt(n))的时间复杂度;坦率地说,如果你有10^10个数据点(谁想等待O(10^5)磁盘读取完成一个简单的范围查询?)

幸运的是,听起来你真的不需要太担心一般情况。因为所有数据都来自时间序列,所以每个时间坐标最多只能有一个值。假设,您可以做的只是使用范围查询来提取一些点的间隔,然后在后处理过程中逐点应用v约束。这将是我尝试的第一件事(在获得一个好的数据库实现之后),如果它有效,那么你就完成了!只有在[t0,t1]x[-infty,+infty]中的点数比[t0、t1]x[v0,v1]中的点的数量大几个数量级的情况下,尝试优化后两个查询才真正有意义。

总体思路:

问题1相当常见:创建一个适合RAM的索引,并链接到辅助存储器上的数据(数据结构:B-树族)。问题2/3相当复杂,因为您的数据太大了。您可以将数据划分为时间范围,并计算该时间范围的最小值/最大值。使用该信息,您可以筛选出时间范围(例如,范围的最大值为50,然后搜索v0>60,则间隔为out)。剩下的需要通过浏览数据来搜索。有效性在很大程度上取决于数据变化的速度。

您还可以通过组合较低级别的时间范围来进行多个索引,以更快地进行筛选。

自行实现这一功能将非常耗时且复杂。我建议你用卡桑德拉。Cassandra可以为您提供水平可扩展性、冗余性,并允许您在未来运行复杂的map reduce函数。要了解如何在cassandra中存储时间序列,请查看:http://www.datastax.com/dev/blog/advanced-time-series-with-cassandra和http://www.youtube.com/watch?v=OzBJrQZjge0.