时间序列:SQL还是NoSQL?


33

我不在乎SQL和NoSQL之间的一般差异(或它们的传统差异)。

我目前正在研究更改内部时间序列的存储方式。它们都包含来自许多不同来源的财务数据。当前,我们将数据存储在专有数据库中。它非常类似于NoSQL,具有自己的查询语言。

我对社区的意见很感兴趣:您如何将数据存储在SQL数据库中?通过NoSQL使用SQL有什么优点,特别是针对时间序列?我为考虑将其存储在SQL中而疯狂吗?

我们的数据集包含数百万个时间序列,其中约10%包含数百万个记录。时间序列是按层次结构组织的:/ Market / Instrument / Value / Frequency,其中:

  • 市场是证券交易所等,基本上是工具的集合,通常是类似的工具。
  • 仪器是一种仪器。这可能是指标(布伦特原油),股票(GOOG)等
  • 值是仪器的多种数据类型之一。可能是收盘价,高价,低价等
  • 频率是特定时间序列值的频率。每周,每天,每月,滴答,任意等

数据如何存储在SQL数据库中?一张大桌子(可能被某些东西隔开),每个市场或工具一张桌子,每个时间序列一张桌子。

先感谢您。


1
所有时间序列是否都包含相同的元数据(即列)?
杰克·道格拉斯

1
听起来像是一个数据仓库……在SO上查看此内容:stackoverflow.com/q/2684462/27535
gbn

@ jack-douglas:您是否要建议一个面向列的数据存储?
尼古拉斯·

3
@Nicolas没想到,传统的SQL RDBMS会非常适合您的数据,因为a)查询起来更容易,b)卷听起来不切实际(数十亿行?)c)日期分区听起来很自然, /或标准OLAP功能。我问有关元数据的问题,以确定您需要多少张表。如果每个时间序列都有唯一的元数据,那么您需要数百万个表,这在常规RDBMS上听起来并不是一个好主意,但是我认为您不需要它,是吗?
杰克·道格拉斯,

2
@Nicolas您是否研究了SQL Server的新Hadoop连接器。从表面上看,您的方案看起来很合适。
Mark Storey-Smith

Answers:


26

通常,对于这样的结构化数据集,我怀疑您可以编写一种自定义数据格式,该格式对于大多数日常操作而言速度更快(即,从任意时间提取少量数据)。迁移到标准数据库工具中可能会带来一些好处,例如临时查询,多路访问,复制,可用性等。雇用维护基于标准的数据存储的帮助也更加容易。

如果要求我建立一个数据库来存储该数据,我将执行以下操作:

拟议方案

(1)核心数据被放入许多(1000个)单独的表中,每个表包含两列:

  1. 时间:SQL DATETIME数据类型或某个时期的数字类型(这是主键)
  2. 值:根据您的数据键入适当的值。我将默认使用单精度浮点数,但是定点数据类型可能更适合金融交易。这可能是未索引的。

这些表将变得非常大,您可能需要按(例如)年份进行手动分区。但是您必须检查系统性能并进行适当调整。

这些表需要唯一的名称,并且有两个选项。它们可以是人类可读的(例如nyse_goog_dailyhighs_2010),也可以是(我偏爱的)随机的。无论哪种方式,都需要一组元数据表,并且随机表名称会阻止开发人员将任何内容推断为不应该被推断的名称。

(2)根据应用程序的要求,元数据存储在单独的表中

需要一个附加表或一组表来跟踪元数据。这些表将包含有关交换,工具,值,频率,日期范围,出处(数据来自何处)以及您需要的其他任何数据。这些映射到数据表名称。

如果有足够的数据,则此查找实际上可以提供表名和数据库名,从而允许某种自我实现的数据分片(如果这是该术语的正确用法)。但是我会保留这一点。

然后在应用程序层,我将查询元数据表以确定我的数据位于何处,然后对大数据表执行相对简单的查询以获取我的数据。

好处:

  • 我的经验(相对有限)是,与处理少量大表相比,数据库通常可以更轻松地处理大量小表。这种方法还可以简化维护工作(例如,清除旧数据,重建损坏的表,从备份创建/重新加载,添加新实体)。如果(例如)您拥有不同速率的数据,或者需要不同的数据类型,那么这将完全解耦不同类型的数据。

  • 这种瘦表的概念还应该允许对最常见的查询(即来自单个实体的连续数据范围)进行快速磁盘访问。大多数数据应用程序都受磁盘I / O限制,因此值得考虑。正如评论员所暗示的那样,这对于面向列的数据库来说是理想的应用程序,但是我还没有找到一种面向主流的列产品,足以让我押注自己的职业。这种模式非常接近。

缺点:

  • 坦率地说,大约有一半的磁盘空间用于存储时间戳,而100或1000的表在timestamp列中的数据完全相同。(实际上,如果要执行简单的表联接,这是必需的)。

  • 存储表名并执行动态查找需要大量的应用程序复杂性和字符串操作,这让我感到有些畏缩。但它似乎仍然比其他方法(下面讨论)要好。

注意事项:

  • 注意在时间范围内四舍五入。您希望您的值足够取整以启用联接(如果适用),但又要足够精确以使模棱两可。

  • 请注意时区和夏令时。这些很难测试。我会在数据存储上执行UTC要求(这可能会使我不受欢迎)并处理应用程序中的转换。

变化:

我考虑过的一些变化是:

数据折叠: 如果时间序列的间隔相等,则使用一个时间戳列和(例如)10个数据列。现在,时间戳是指第一个数据列的时间,并且假设其他数据列在该时间戳和下一个时间戳之间均等间隔。这样可以节省大量以前用于存储时间戳的存储,但会带来大量的查询和/或应用程序复杂性。连续范围的单个实体查询现在需要较少的磁盘访问权限。

多路复用如果已知多个时间序列使用相同的时间序列,则如上所述使用一个时间戳和(例如)10个数据列。但是现在每一列代表一个不同的时间序列。这需要对元数据表进行更新,而不是对表和列名称的查找。存储空间减少。查询保持简单。无论范围如何,单个实体查询现在都需要更多的磁盘访问权限。

兆表: 将“多重复用”概念发挥到极致,并将所有数据放入一个表中,每列时间序列一次。对于连续范围,单个实体查询,这需要大量磁盘访问,这是维护的噩梦。例如,现在添加新实体需要在多个TB表上使用MODIFY TABLE命令。

有关此格式的更多讨论,请参见以下内容中的各种答案: MySQL中的列过多

完全规范化的表: 可以使用一个三列表,而不是使用许多2列表,其中的列是时间,数据ID和值。现在,您的元数据表只需要查找ID值,而不是表名或列名,从而可以将更多逻辑推入SQL查询而不是应用程序层。

现在,规范化列消耗了大约2/3的存储空间,因此这将占用大量磁盘空间。

您可以将主键顺序(数据ID,时间戳)用于快速连续的单个实体查询。或者,您可以使用主键顺序(timestamp。dataid)来加快插入速度。

但是,即使考虑了这些变化之后,我的下一个开发计划还是有很多表,每个表有两个列。那,或者该方法很快就会被比我聪明的人发布:)。


非常感谢您的回答。您提出了一些非常有效的观点。我完全同意存储在UTC中。我正在执行所有数据都传递到UTC的前端(Web,桌面和移动)的想法。我们有跨国客户,操作系统应该负责时间转换。我有一个DBA公司在处理我们的整个数据集,不知道其他人会提出什么。再次感谢。
尼古拉斯

当DBA顾问致力于针对强大的SQL Server安装进行定位时,我将继续使用BigData安装进行测试。
尼古拉斯

也许这是一个很好的解决方案,但是真正的“时间序列”应用程序应该支持“放大到数据”功能,而数据库对此无能为力。时间序列数据库更多关于聪明的“放大”和“缩小”。
Roman Pokrovskij

1

使用MongoDB,您可以非常快速地创建集合。着眼于将数据安排到单独的数据库中以及这些数据库中的集合。考虑一下需要多少内存来尝试将每个分片保留在系统内存中-如果需要快速检索。坚持使用内部解决方案很愚蠢,如果有新鲜事物可以按照您的需要发展。听起来像个好主意。


2
您将如何在Mongo中存储时间序列?每个文件都是一个时间序列?或特定时间戳记的值?
RockScience 2012年

为了有效地针对非周期性甚至周期性数据执行此操作,最好预先分配数据块。每个块都是一个带有少量簿记数据的文档,一个固定大小的数组用于您的值,一个固定大小的数组用于您的时间。然后,您可以将系列的元数据存储在单独的文档中。在此元数据文档中,维护一个小的嵌套文档,该文档将充当您的数据段的簿记员,即跟踪当前数组索引和段_id。
RYS
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.