2

我正在考虑使用 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)Camera-wise Collections:创建100个MongoDB Collections,即每个Camera 1个Collection(100个camera/collections)。然后以 (20141122061055000) 之类的格式保存具有唯一“id”的快照,这是对完整日期时间戳 (2014-11-22 06:10:55.000) 的改写。

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

考虑到我的情况,请就我对 MongoDB 的选择提出建议。

问候。

4

2 回答 2

5

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

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

在 MongoDB 中以这种方式使用许多集合被认为是一个坏主意(并且您很可能在索引开销之后为此增加 ns 大小),您应该改为横向扩展单个通用文档集合。其他回答者似乎同意。

我会使用单个集合,其文档结构可能是(快速离开我的头顶):

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

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

注意:还要考虑 MongoDB 的锁是数据库级别的,而不是集合级别的。您不会在这里获得任何有用的信息,只会使您的查询更加困难和复杂,并且可能会使您的数据更难维护。

编辑

回答您的一些担忧:

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

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

再说一次,我真的不明白这一点,如果您出于优化原因这样做,那么您将作为每个 DB 一台摄像机来执行此操作,但这正式过分。老实说,3000 万条记录不算什么,我现在就解决这个问题。无论您是在谈论 SQL 还是 MongoDB,就数据库潜力而言,30m 的记录集合通常被认为是很小的,甚至是分钟(MS SQL 表示它们可以存储每个表的 PB 数据)。

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

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

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

你可以count()

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

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

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

然后你可以在几天内增加一些,因为count()在大型工作集上会变慢。因此,收集的目的是总结您的数据,以使您的查询工作集更易于管理。

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

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

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

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

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

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

这应该工作得很好。

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

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

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

这一切都归结为分片。至于它是否会很快取决于要运行的查询和它们的工作集大小(RAM中需要多少数据,是否在RAM中?)。从外观上看, image_id ( ObjectId) 和 date 上的分片索引可能会给你你想要的。然而,这需要更多的测试,因为我相信你对扩展数据库有点陌生,你真的应该通过谷歌或其他东西对这个主题进行一些搜索。

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

希望这会有所帮助,而且我还没有在这里绕圈子,

于 2012-11-03T12:48:54.530 回答
2

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

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

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

于 2012-11-03T08:17:24.843 回答