静态时间序列数据的数据库解决方案

时间:2013-07-25 18:15:05

标签: database matlab database-design time-series

我们拥有大量且不断增长的实验数据数据集,这些数据来自约30,000名受试者。对于每个主题,有几个数据记录。在每个记录中,存在几个时间序列的生理数据集合,每个序列长约90秒并以250Hz采样。我应该注意,任何给定的时间序列实例都不会扩展,只会在数据集中添加其他记录。这些录音也是 所有相同的长度。目前,每个记录的数据都包含在自己的平面文件中。这些文件按照目录结构进行组织,该结构按整个实验版本,实验位置,日期和实验终端(按层次顺序)分层次细分。

我们的大部分分析都是在MATLAB中完成的,我们计划继续广泛使用MATLAB进行进一步分析。当所有研究人员共同定位时,目前的情况是可行的(如果不可取的话)。我们现在遍布全球,我正在研究最佳解决方案,以便从远程位置提供所有这些数据。我精通MySQL和SQL Server,并且很容易想出一种在这种范例内构建这些数据的方法。但是,我对这种方法的效率持怀疑态度。我会重视任何可能指向正确方向的建议。我应该考虑不同的东西吗?时间序列数据库(虽然我认为这些数据库可用于扩展现有的时间序列)?还有别的吗?

分析不需要在线完成,但这样做的可能性更大。目前,我们的典型用例是查询特定的记录子集并下拉相关的时间序列以进行本地分析。我很感激您的任何建议!

更新

在我的研究中,我发现this paper,他们在那里存储和分析非常相似的信号。他们之所以选择MongoDB,原因如下:

  • 发展速度
  • 向现有文档添加字段的便利性(从信号中提取的特征等)
  • 通过MongoDB API本身轻松使用MapReduce

这些对我来说都是有吸引力的优势。开发看起来很简单,用分析结果轻松扩充现有文档的能力显然很有帮助(虽然我知道在我已经熟悉的系统中这并不是很难做到。

要清楚,我知道我可以将数据保存在平面文件中,我知道我可以通过网络安排通过MATLAB安全访问这些平面文件。我想将这些数据存储在数据库中有众多原因。例如:

  • 现在平面文件的结构很少,除了上面提到的层次结构。例如,如果没有为特定日期的每个终端提取所有单个文件,就无法从特定日期提取所有数据。
  • 无法查询与特定录制相关联的元数据。例如,我不禁想起我需要跳过来为女性主题提取所有数据的箍。

它的长短之处在于我想将这些数据存储在数据库中,原因有很多(空间,效率和访问易用性等等)。

更新2

我似乎没有充分描述这些数据的性质,因此我将尝试澄清。这些录音肯定是时间序列数据,但不像许多人想到的时间序列。我不是在不断捕获要附加到现有时间序列的数据。我正在制作多个录音,所有录音都有不同的元数据,但是有相同的三个信号。这些信号可以被认为是数字矢量,并且这些矢量的长度因记录而异。在传统的RDBMS中,我可能会为记录类型A创建一个表,为B等创建一个表,并将每一行视为时间序列中的数据点。但是,这不起作用,因为录音的长度不同。相反,我更愿意拥有一个代表一个人的实体,并且该实体与从该人那里获得的几个记录相关联。这就是我考虑MongoDB的原因,因为我可以在一个集合中的一个对象中嵌套几个数组(不同长度)。

潜在的MongoDB结构

作为一个例子,这是我为一个主题绘制的潜在MongoDB BSON结构:

{
    "songs": 
    {
        "order": 
        [
            "R008",
            "R017",
            "T015"
        ],
        "times": [
            { 
                "start": "2012-07-02T17:38:56.000Z",
                "finish": "2012-07-02T17:40:56.000Z",
                "duration": 119188.445
            },
            { 
                "start": "2012-07-02T17:42:22.000Z",
                "finish": "2012-07-02T17:43:41.000Z",
                "duration": 79593.648
            },
            { 
                "start": "2012-07-02T17:44:37.000Z",
                "finish": "2012-07-02T17:46:19.000Z",
                "duration": 102450.695
            }
        ] 
    },
    "self_report":
    {
        "music_styles":
        {
                "none": false,
                "world": true
        },
        "songs":
        [
            {
                "engagement": 4,
                "positivity": 4,
                "activity": 3,
                "power": 4,
                "chills": 4,
                "like": 4,
                "familiarity": 4
            },
            {
                "engagement": 4,
                "positivity": 4,
                "activity": 3,
                "power": 4,
                "chills": 4,
                "like": 4,
                "familiarity": 3
            },
            {
                "engagement": 2,
                "positivity": 1,
                "activity": 2,
                "power": 2,
                "chills": 4,
                "like": 1,
                "familiarity": 1
            }
        ],
        "most_engaged": 1,
        "most_enjoyed": 1,
        "emotion_indices":
        [
            0.729994,
            0.471576,
            28.9082
        ]
    },
    "signals":
    {
        "test":
        {
            "timestamps":
            [
                0.010, 0.010, 0.021, ...
            ],
            "eda":
            [
                149.200, 149.200, 149.200, ...
            ],
            "pox":
            [
                86.957, 86.957, 86.957, ...
            ]
        },
        "songs":
        [
            {
                "timestamps":
                [
                    0.010, 0.010, 0.021, ...
                ],
                "eda":
                [
                    149.200, 149.200, 149.200, ...
                ],
                "pox":
                [
                    86.957, 86.957, 86.957, ...
                ]
            },
            {
                "timestamps":
                [
                    0.010, 0.010, 0.021, ...
                ],
                "eda":
                [
                    149.200, 149.200, 149.200, ...
                ],
                "pox":
                [
                    86.957, 86.957, 86.957, ...
                ]
            },
            {
                "timestamps":
                [
                    0.010, 0.010, 0.021, ...
                ],
                "eda":
                [
                    149.200, 149.200, 149.200, ...
                ],
                "pox":
                [
                    86.957, 86.957, 86.957, ...
                ]
            }
        ]
    },
    "demographics":
    {
        "gender": "female",
        "dob": 1980,
        "nationality": "rest of the world",
        "musical_background": false,
        "musical_expertise": 1,
        "impairments":
        {
            "hearing": false,
            "visual": false
        }
    },
    "timestamps":
    {
        "start": "2012-07-02T17:37:47.000Z",
        "test": "2012-07-02T17:38:16.000Z",
        "end": "2012-07-02T17:46:56.000Z"
    }
}

那些signal是时间序列。

3 个答案:

答案 0 :(得分:1)

当人们来到NoSQL数据库时,他们常常听到没有架构和生活都很好。但是,恕我直言,这是一个非常错误的观念。

在处理NoSQL时,你必须考虑"聚合" 。通常,聚合体是可以作为单个单元操作的实体。在您的情况下,一种可能(但不是那么有效)的方式是将用户和他/她的数据建模为单个聚合。这将确保您的用户聚合可以是数据中心/分片不可知。但是如果数据将会增长 - 加载用户也将加载所有相关数据并成为内存耗尽。 (Mongo本身在内存上有点贪心)

另一种选择是将录音存储为聚合和"链接"返回具有id的用户 - 这可以是您可以像GUID一样创建的合成密钥。即使这表面看起来像是一个联合,它只是一个"通过财产" - 因为这里没有真正的参照完整性。如果文件不断添加,这可能是我采取的方法。

MongoDb闪耀的地方是您可以通过文档中的属性进行特殊查询的部分(如果您不想在以后丢失头发,则会为此属性创建索引。)。您在Mongo中选择时间序列数据存储时不会出错。您可以在日期范围内提取与ID匹配的数据,例如,不进行任何重大特技。

请确保您拥有副本集,无论您采用哪种方法,并尽早选择分片方法 - 稍后分片并不好玩。

答案 1 :(得分:0)

我觉得这可能无法回答正确的问题,但这是我可能会采用的(使用SQL服务器):

用户(表格)

  • 用户ID
  • 性别
  • 鉴定
  • 等...

样本(表格)

  • SampleId
  • 用户ID
  • STARTIME
  • 持续时间
  • 顺序
  • 等...

系列(表)

  • SampleId
  • SecondNumber(约1-90)
  • 值(带值的字符串)

我认为这应该为您提供相当灵活的访问,以及合理的内存效率。由于值以字符串格式存储,因此您无法对sql中的时间序列进行分析(它们需要先进行解析),但我不认为这应该是一个问题。当然,您也可以使用MeasurementNumberValue,然后您就可以完全自由了。

当然,这不像MongoDB设置那么完整,但差距应该很容易填补。

答案 2 :(得分:0)

您应该真正调查LDAP及其数据模型。显然,您的数据具有强大的层次结构特征,LDAP已经常用于存储有关人员的属性。它是一个成熟的标准化网络协议,因此您可以从各种实现中进行选择,而不是被锁定在特定的NoSQL风格的月份选择中。 LDAP专为分布式访问而设计,为身份验证(以及授权/访问控制)提供安全模型,并且非常高效。比任何这些基于HTTP的协议都要多。