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

the*_*ter 2 mongodb nosql

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

选择摄像机>选择日期>选择小时>获取该小时内的所有图像.

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

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

2)日常收藏:创建3000个MongoDB收藏,即每个摄像机每天1个收集(100个摄像机X 30天).虽然这是允许的,并且看起来收集的数量很多,但我关心的是从特定日期内的特定时间内阅读图像.

3)逐照摄像机集合:创建100个MongoDB集合,即每个摄像机1个集合(100个摄像机/集合).然后以(20141122061055000)格式保存具有唯一"id"的快照,这是对完整日期时间戳的重新描述(2014-11-22 06:10:55.000).

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

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

问候.

Sam*_*aye 5

这继续:使用MongoDB而不是MS SQL Server的优点和缺点.

我不确定你为什么要尝试使用许多收藏品.

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

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

{
    _id: {},
    camera_id: ObjectId(),
    image: {},
    hour: ts_of_hour,
    day: ts_of_day
}
Run Code Online (Sandbox Code Playgroud)

这样,您就可以获得根据您想要的任何面额选择图像所需的所有数据.

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

编辑

回答你的一些担忧:

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

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

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

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

您可以使用上面的答案使用文档上的BSON日期字段来完成此操作.

  1. 在FromDate和ToDate之间选择Top(COUNT)个图像

你可以count().

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

您可以将此特定数据聚合到另一个集合.这没关系,所以在另一个系列中你会有一些日子:

{
     count: 3,
     day: (date|ts)
}
Run Code Online (Sandbox Code Playgroud)

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

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

基本上,就像在SQL中一样,公共模式或文档在集合中进行分组.所以我真的只用一个表在SQL中设计你的应用程序:images也许camera也是如此.

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

  1. 从具有ID的图像中选择上一个/下一个图像

您可以_id像这样使用这里:

db.images.find({_id: {$gt: last_id}}).limit(1)
Run Code Online (Sandbox Code Playgroud)

这应该工作得很好.

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

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

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

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

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

希望这有帮助,我没有在这里绕圈子,