什么是存储时间序列的有效方法?

时间:2014-08-20 22:21:30

标签: compression time-series

我的数据量很大,格式很糟糕:包含csv个文件的16.4GiB zip文件。 每个csv都包含

之类的行
TYPE,2014-07-02 04:04:23.806,0.94598,0.94607

基本上:

  • A TYPE(有14种不同的类型,将来可以理想地增长)
  • A timestamp(以毫秒为单位)
  • 2个浮点数(最多5个小数位),通常有一点点差
  • 相同TYPE的所有浮点数在它们及时关闭时通常具有非常相似的值
  • 时间戳之间的差值小于1秒
  • 数据跨度为5年

总共我有3' 091'' 167行,所以我们说的是数十亿。 主要操作将循环部分或全部数据集(为了在数据上运行算法),每月插入一次约2千万条记录(但插入数据不是我对优化感兴趣的东西)对)。

理想的解决方案是将它们存储在一个数据库中以便我可以轻松地查询它们,但是一些粗略的计算表明我需要46GiB和Postgres一起使用(其中一些可能会被降低到18GiB丑陋的技巧)。

我已经使用我拥有的数据完成了一些experiments,我发现:     生成包含TIMESTAMP,FLOAT1,FLOAT2的gzip压缩文件会让我达到~14GiB     完全删除时间戳会让我降到~5GiB

节省空间的好方法是以有效的方式存储时间戳。 我正在考虑创建一个树结构,其中每个节点都包含一个时间戳数字,其中叶子包含最后一个数字和两个浮点数。

我已经尝试过像druid.io这样的解决方案,但看起来他们正试图针对我的用例并不需要的其他事情进行优化。

是否有一些我失踪的工具正是我想要的? 如果不是,那么存储时间序列数据的有效方法是什么?

谢谢

3 个答案:

答案 0 :(得分:5)

在PostgreSQL方面,您还可以使用开源列式存储。这可以免费获得压缩,柱状布局和跳过索引。存储和磁盘I / O相关的好处是:

  1. 由于列值按顺序存储,因此压缩率会更高
  2. 数据库仅读取您要查询的列,并跳过其余列
  3. cstore_fdw构建轻量级跳过索引。对于时间序列数据,这些索引会自动过滤不相关的数据。
  4. 了解更多信息:https://news.ycombinator.com/item?id=7523950

    如果您还需要将查询扩展到多个CPU核心/机器,则可以使用可扩展的PostgreSQL:http://www.citusdata.com/downloads

    除了压缩和高效的数据布局之外,您还可以免费获得PostgreSQL的类型检查,数据操作功能及其所有查询功能。

答案 1 :(得分:1)

我会:

  1. 将数据分成几千个段,按时间分组。我不知道时间的推移,但也许每小时都有一个文件。

  2. 按时间戳将它们存储在子目录中。例如。 2014/07/02/04。

  3. 开始时间戳记放在文件名中。例如。 2014-07-02 04:04:23.806.gz

  4. 对于所有行,将类型存储为第一个字节中的索引。这允许扩展到256种类型。如果这还不够,请将其设为两个字节。

  5. 对于所有行,时间戳是一个双字节整数,并且浮点数是带符号的n字节整数,足以保持值乘以10 5 。我假设这些浮点值的范围有限。每个四个字节就足够了。

  6. 对于第一行,时间戳为零,表示与该行的时间和文件名的差异。

  7. 对于第一行,浮点值是实际值。

  8. 对于所有后续行,时间和浮点值是与上一行的差值。请注意,它们可能是否定的。

  9. 交错值的最重要字节,以最大限度地为小增量运行零。

  10. 使用zlib压缩每个文件。除默认模式外,请尝试使用Z_FILTEREDZ_HUFFMAN模式查看压缩效果是好还是差。

答案 2 :(得分:-1)

绝对使用数据库。 PostgreSQL时间戳字段各为8个字节。如果您使用smallint代表TYPEreal作为数据值(小数点后6位精度),则每行18个字节或当前数据集超过55个字节。没有索引或讨厌的黑客。

似乎过分关注存储空间。千兆字母不贵。您花在尝试从存储中获取数据的时间可能更昂贵。时间戳字段对此非常有用,因为它提供了非常细粒度的索引,并允许数据库快速检索所需的记录。

将您的数据放入数据库,使表格的主键成为TYPETIMESTAMP的组合,然后投资SSD来保存数据。