在MongoDB中拥有大量集合(需要架构设计建议)

时间:2012-11-03 07:58:12

标签: mongodb nosql

我正在考虑使用MongoDB来保存从100台摄像机录制的图像元数据,并且每台摄像机的记录将保留30天。如果一台摄像机每天提供100,000张图像,那么我将在MongoDB中以最大值保存( 100 x 30 x 100000 )图像(文档)。我的Web应用程序将查询此数据:

选择相机>选择日期>选择一小时>在那个小时内获取所有图像。

我计划使用以下三个选项设计架构,并需要您的专家意见/建议以获得最佳出路;

1)按小时收集:创建 72000个MongoDB收藏,即每个相机每小时收集一次(100个相机X 30天X 24小时)(使用--nssize 500命令超过24000限制)。我担心如果MongoDB允许我创建这么多的集合,其次是在阅读和写入这些集合时预期的性能优势和损失。虽然,对于每小时读取图像看起来非常容易使用此模式,因为我可以在单个查询中将数据提取到任何集合。

2)日常收藏:创建 3000个MongoDB收藏,即每个相机每天收集一次(100个相机X 30天)。虽然这是允许的,并且看起来收集的数量很多,但我关注的是从特定日期内的特定小时读取图像。

3)按照相机收藏:创建 100个MongoDB收藏,即每个相机的收藏(100个相机/收藏品)。然后保存具有唯一“id”的快照,格式如(20141122061055000),这是对完整日期时间戳的重新描述(2014-11-22 06:10:55.000)。

我希望理想情况下我可以做(1),(2)或(3)但欢迎任何其他选择。

考虑到我的情况,请建议我选择MongoDB。

问候。

2 个答案:

答案 0 :(得分:5)

这是继续:Pros and Cons of using MongoDB instead of MS SQL Server

我不确定您为什么要尝试使用许多集合。

在MongoDB中以这种方式使用许多集合被认为是一个坏主意(并且你必须在索引开销之后增加ns大小),你应该在水平方向上扩展单个常用文档集合。似乎其他的回答者同意了。

我会使用一个带有文档结构的集合(快速脱离我的头脑):

{
    _id: {},
    camera_id: ObjectId(),
    image: {},
    hour: ts_of_hour,
    day: ts_of_day
}

通过这种方式,您可以获得根据您想要的任何面额选择图像所需的所有数据。

注意:同样考虑MongoDBs锁是数据库级别,而不是集合级别。你不会在这里获得任何有用的东西,只会使你的查询变得更难,更复杂,并且可能使你的数据难以维护。

修改

回答您的一些疑虑:

注意:我没有设计你的应用程序,这是一个迟到的答案(深夜也是如此),所以基本上这是我充实的基本概念,立即浮现在脑海中。

  

每个相机1个集合,即几乎100个集合。

我再也不明白这一点,如果你出于优化原因这样做,那么你会把它作为每个数据库的一个摄像头,但这是正式的矫枉过正。老实说,3000万条记录什么都没有,我现在就解决这个问题。无论您是在谈论SQL还是MongoDB,在数据库潜力方面,30米记录集通常被认为是小的,甚至是微小的(MS SQL表示它们可以存储每个表的perabytes)。

  
      
  1. 选择FromDate和ToDate 2之间的所有图像
  2.   

您可以使用上述答案在文档上使用BSON日期字段来完成此操作。

  
      
  1. 在FromDate和ToDate之间选择热门(COUNT)图像
  2.   

你可以count()

top()未在所有数据库系统中实现,因此这是MS SQL特定的,但在此特定查询中它没有任何用处,因为该查询将始终返回一行。

您可以将此特定数据聚合到另一个集合。这很好,所以在另一个集合中你会有一些日子:

{
     count: 3,
     day: (date|ts)
}

然后你可以在count()在一个大型工作集上变得缓慢的几天内完成。因此,该集合的目的是汇总您的数据,使您的查询工作集更易于管理。

因此,其他集合可用于保存聚合函数的“缓存”,这些函数速度很慢,或者当然可以在应用程序中保存其他实体(就像关系数据库那样)。

基本上,就像在SQL中一样,常见的模式或文档会在集合中进行分组。所以我真的只用一个表来设计你的应用程序:images也许camera

除了5之外的所有其他人都被宽松地覆盖在这里:

  
      
  1. 从/带有ID
  2. 的图像中选择上一张/下一张图像   

您可以像这样使用_id

db.images.find({_id: {$gt: last_id}}).limit(1)

这应该可以很好地运作。

至于你在这里发表的评论:

  

你的意思是在MongoDB中,查询包含30个文档的集合与查询具有30,00,000个文档的集合没有什么区别吗?

现在,这取决于您对数据库设计的了解程度以及如何扩展数据库体系结构。这不仅适用于MongoDB,也适用于SQL。如果设置正确,SQL可以轻松查询30m记录,如30。

归结为什么是分片。至于它是否会快速下降到你的索引跨越那些运行查询的分片及其工作集大小(RAM中需要多少数据,是否在RAM中?)。通过它的外观,image_id(ObjectId)上的分片索引和日期可能会给你你想要的东西。然而,这将需要更多测试,因为我相信你对扩展数据库有点新意,你应该通过Google或其他东西对这个主题进行一些搜索。

再次注意:30万个文档可能不需要分片,所以这可能只是制作好的索引。

希望这会有所帮助,而且我没有绕过这里,

答案 1 :(得分:2)

我没有看到你的收藏问题。照片是一个单独的方案,它们应该在一个集合中。

每张照片都有一张时间戳。其余的由querying完成。您可以每小时查询文档而不会出现问题:

var begin_hour = new Date(date.year, date.month, date.day, hour);
var end_hour = new Date(date.year, date.month, date.day, hour + 1);

db.photos.find({taken: {$gte: begin_hour, $lt: end_hour}})

这将按所选的hour选择照片。

如果这不满足你,那么还有MapReduce

相关问题