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

Database 静态时间序列数据的数据库解决方案,database,matlab,database-design,time-series,Database,Matlab,Database Design,Time Series,我们有一个庞大且不断增长的实验数据集,来自大约30000名受试者。对于每个受试者,都有一些数据记录。在每次记录中,都会收集一些生理数据的时间序列,每个数据约90秒长,以250Hz的频率采样。我应该注意到,时间序列的任何给定实例都不会被扩展,只会向数据集添加额外的记录。这些录音也不是长度相同的。目前,每个记录的数据都包含在自己的平面文件中。这些文件组织在一个目录结构中,该目录结构按整个实验的版本、实验位置、日期和实验终端(按该层次顺序)进行分层分解 我们的大部分分析都是在MATLAB中完成的,我们

我们有一个庞大且不断增长的实验数据集,来自大约30000名受试者。对于每个受试者,都有一些数据记录。在每次记录中,都会收集一些生理数据的时间序列,每个数据约90秒长,以250Hz的频率采样。我应该注意到,时间序列的任何给定实例都不会被扩展,只会向数据集添加额外的记录。这些录音也不是长度相同的。目前,每个记录的数据都包含在自己的平面文件中。这些文件组织在一个目录结构中,该目录结构按整个实验的版本、实验位置、日期和实验终端(按该层次顺序)进行分层分解

我们的大部分分析都是在MATLAB中完成的,我们计划继续广泛使用MATLAB进行进一步的分析。当所有研究人员都在同一地点时,目前的情况是可行的(如果不可取的话)。我们现在遍布全球,我正在研究从远程位置获取所有这些数据的最佳解决方案。我精通MySQL和SQL Server,可以很容易地想出一种方法,在这样的范例中构造这些数据。然而,我对这种方法的效率表示怀疑。我会重视任何可能为我指明正确方向的建议。我应该考虑一些不同的事情吗?时间序列数据库(尽管在我看来,这些数据库似乎是为了扩展现有的时间序列而调整的)?还有别的吗

分析不需要在网上进行,尽管这样做的可能性会更好。目前,我们的典型用例是查询特定的记录子集,并下拉相关的时间序列进行局部分析。我很感激你的任何建议

更新: 在我的研究中,我发现,它们在哪里存储和分析非常相似的信号。他们选择MongoDB的原因如下:

  • 发展速度
  • 向现有文档中添加字段的方便性(从信号中提取的特征等)
  • 通过MongoDB API本身易于使用MapReduce
这些对我来说都是有吸引力的优势。开发看起来非常简单,使用分析结果轻松扩充现有文档的能力显然很有帮助(尽管我知道在我已经熟悉的系统中这样做并不困难)

说清楚一点,我知道我可以将数据存储在平面文件中,我知道我可以通过网络通过MATLAB安全地访问这些平面文件。我希望将这些数据存储在数据库中的原因有很多。例如:

  • 除了上面提到的层次结构之外,平面文件现在几乎没有什么结构。例如,如果不在某一天为每个终端下拉所有单独的文件,就不可能从某一天提取所有数据
  • 无法查询与特定录制相关的元数据。例如,想到要获取女性受试者的所有数据,我会不寒而栗
长话短说,我希望将这些数据存储在数据库中,原因有很多(空间、效率和易访问性等)

更新2 我似乎没有充分描述这些数据的性质,因此我将尝试澄清。这些记录当然是时间序列数据,但不是许多人认为的时间序列。我没有不断捕获数据以附加到现有的时间序列。我确实在进行多个记录,所有记录都具有不同的元数据,but相同的三个信号。这些信号可以被认为是一个数字向量,这些向量的长度随着记录的不同而不同。在传统的RDBMS中,我可能会创建一个记录类型a的表,一个记录类型B的表,等等,并将每行视为时间序列中的一个数据点。但是,这不起作用,因为记录的长度不同h、 相反,我更希望有一个表示一个人的实体,并将该实体与从该人处获取的多个录音相关联。这就是我考虑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"
    }
}

那些信号是时间序列。

很多时候,当人们来到NoSQL数据库时,他们听到没有模式,生活都很好。然而,我认为这是一个非常错误的概念

在处理NoSQL时,您必须从“聚合”的角度来考虑。通常,聚合是一个可以作为单个单元操作的实体。在您的情况下,一个是可能的(但不是那么有效)方法是将用户和他/她的数据建模为单个聚合。这将确保您的用户聚合与数据中心/碎片无关。但如果数据增长,加载用户也将加载所有相关数据并占用内存。(Mongo本身对内存有点贪婪)

另一种选择是将录制存储为聚合,并使用id“链接”回用户-这可以是一个合成键,您可以像GUID一样创建。尽管这表面上看起来像一个连接,但它只是一个“按属性查找”-因为这里没有真正的引用完整性。如果要不断添加文件,我可能会采用这种方法

MongoDb的亮点在于,您可以通过文档中的属性进行临时查询(如果您不想在以后失去头发,您将为此属性创建一个索引)。您在Mongo中选择时间序列数据存储不会出错。您可以在d中提取与id匹配的数据