用于查询日期范围的最佳NoSql?

时间:2011-04-18 16:44:34

标签: mongodb cassandra redis couchdb nosql

给定一个商店,它是(近似)形式的JSON文档集合:

{
PeriodStart: 18/04/2011 17:10:49 
PeriodEnd: 18/04/2011 17:15:54
Count: 12902
Max: 23041 Min: 0
Mean: 102.86 StdDev: 560.97
},
{
PeriodStart: 18/04/2011 17:15:49 
PeriodEnd: 18/04/2011 17:20:54
Count: 10000
Max: 23041 Min: 0
Mean: 102.86 StdDev: 560.97
}... etc

如果我想查询给定日期范围的集合(比如说过去24小时内的所有文档),这会给我最简单的查询操作吗?

进一步详细说明要求:

  • 它用于应用程序监控服务,因此不一定需要严格的CAP / ACID
  • 表现也不是首要考虑因素。读/写最多每秒10秒,无论如何都可以由RDBMS处理
  • 能够处理更改文档架构的能力
  • 轻松查询列表/集合的能力很重要(ad-hoc查询有利)

8 个答案:

答案 0 :(得分:6)

我可能没有准确地查询您的查询要求,因为您没有指定。但是,如果您需要查找在特定范围内开始或结束的任何文档,则可以应用下面所写的大部分内容。如果这不是你想要的,那么我可以更多地帮助我们。 :)

如果使用CouchDB,则可以通过将日期部分拆分为数组来创建索引。 ([year, month, day, hour, minute, second, ...]

您的地图功能可能类似于:

function (doc) {
    var date = new Date(doc.PeriodStart);
    emit([ date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes() ] , null]);
}

要执行任何类型的范围查询,您需要将开始和结束时间转换为相同的数组结构。从那里,您的查看查询将包含名为startkeyendkey的参数。他们将分别收到开始和结束的数组参数。

因此,要查找过去24小时内开始的文档,除了视图本身的完整URI之外,还会发送这样的查询字符串:

// start: Apr 17, 2011 12:30pm ("24 hours ago")
// end:   Apr 18, 2011 12:30pm ("today")
startkey=[2011,04,17,12,30]&endkey=[2011,04,18,12,30]

或者如果您想要今年的所有内容:

startkey=[2011]&endkey=[2011,{}]

请注意{}。用作结束键时:[2011,{}]与整理视图时的[2012]相同。 (任何一种格式都可以使用)

数组的额外组件将被忽略,但是您添加到阵列的进一步特异性,您的范围就越具体。如果添加group_level参数,添加reduce函数在这里可能非常强大,但这超出了您的问题的范围。

答案 1 :(得分:1)

[更新编辑以匹配原始问题的编辑]

简短回答,(差不多)其中任何一个都能奏效。

BigTable数据库是监控服务(日志分析等)的绝佳平台。我更喜欢Cassandra(Super Column Families,二级索引,即将到来的原子增量),但HBase也适合你。构造日期值,使其字典顺序与日期排序相同。格式为“YYYYMMDDHHmmss”的固定长度字符串可以很好地工作。如果您使用此字符串作为键,则范围查询将非常简单执行。

处理更改架构非常简单 - 只需向列族添加更多列。它们不需要提前定义。

我可能不会使用图形数据库来解决这个问题,因为它可能会总结为遍历链表。但是,我对图形数据库没有太多的经验,所以请大家多加一点。

[更新:自问题被编辑以来,其中一些是没有实际意义的,但我为后人保留了这一点] 这是所有你正在使用这个数据库吗?选择NoSQL数据库的一个大问题是找不到支持一个查询要求的问题。问题是找到一个支持所有您的查询要求的人。另外,您的运营要求是什么?你能接受单点故障吗?您愿意容忍哪种设置/维护开销?您是否可以牺牲高吞吐量批处理操作的低延迟,或实时您的演出?

希望这有帮助!

答案 2 :(得分:1)

在我看来,实现所需内容的最简单方法是在 ElasticSearch 等搜索引擎中执行range query

我当然不想为CouchDB编写所有map / reduce代码(因为我以前做过)。此外,根据我的经验(YMMV),范围查询将优于CouchDB的视图,并且对大型数据集使用更少的资源。

更不用说您可以使用 ElasticSearch 中的„date histogram“ facets计算有趣的统计信息。

ElasticSearch 是无架构的,基于JSON的,因此您应该能够在很短的时间内为您的案例评估它。

答案 3 :(得分:1)

我决定暂时和Mongo一起去。

我发现设置/部署相对容易,C# wrapper足以满足我们的目标(在我们不能轻易使用javascript查询的情况下)。

答案 4 :(得分:0)

你想要的是任何一个让你访问某种空间索引的人。其中大部分都是用B树和/或哈希来完成的,这些都不是特别适合空间索引。

现在,如果你的“过去24小时”的定义只是“在过去24小时内开始或结束”,那么可能会找到一个B树(你做两个查询,一个在PeriodStart上,然后一个在PeriodEnd上,两个在时间范围内)。

但是如果PeriodStnd到PeriodEnd的时间长于时间窗口,那么这些都不会对你有任何帮助。

无论哪种方式,这就是你要找的东西。

答案 5 :(得分:0)

This question说明了如何在CouchDB中查询日期范围。在我看过的所有例子中,您都需要您的数据处于按字典顺序排序的状态。

答案 6 :(得分:0)

由于这是标记为Redis而没有人回答这个问题,我将提出解决方案。

第一步,将文档存储在给定的redis密钥下,作为哈希或可能作为JSON字符串。 第二步,在排序集中添加redis密钥(让我们称之为DocID),并将时间戳转换为UNIX时间戳。例如,其中r是Python redis客户端库中的redis Connection实例:

mydocs:Doc12 => [doc的JSON字符串]

在Python中: r.set('mydocs:Doc12',JSONStringOfDocument)

timeindex:文档,DocID,时间戳:

在Python中: r.zadd('timeindex:documents','Doc12',timestamp)

实际上,您正在构建基于UNIX时间戳的文档索引。

要从一段时间内获取文档,您可以使用zrange(或zrevrange如果您想要反转订单)获取该窗口中的文档ID列表。然后您可以正常从db中检索文档。 Redis中的排序集非常快。进一步的优点是你可以设置诸如“这个窗口中的文档而不是这个窗口”之类的操作,甚至可以自动将结果存储在Redis中供以后使用。

这有用的一个示例是,在您的示例文档中,您有一个开始和结束时间。如果您按上述方式创建了每个索引,则可以获得在给定范围内开始的文档集与在给定范围内结束的文档集的交集,并将结果集存储在新密钥中以供以后重新使用。 -使用。这可以通过zinterstore

完成

希望这有助于使用Redis的人。

答案 7 :(得分:0)

Mongodb对查询非常积极,我认为它很有用,因为它有很多功能。我使用mongodb进行GPS距离,文本搜索和管道模型(聚合包括)