MongoDB 结构:单个集合与多个较小的集合
Posted
技术标签:
【中文标题】MongoDB 结构:单个集合与多个较小的集合【英文标题】:MongoDB structure: single collection vs multiple smaller collections 【发布时间】:2012-11-27 11:47:22 【问题描述】:我有一个一般性的数据库结构问题。在我的场景中,我碰巧正在使用 mongodb。
我正在创建一个应用程序,用户可以在其中上传歌曲列表(标题、艺术家等),但我不确定我是否应该为所有用户创建一个 songList 集合,还是为每个用户创建一个单独的 songList.user# 集合个人用户。用户只能查询与他们关联的歌曲,因此用户 A 永远不会知道用户 B 的歌曲。
代码示例:
每个用户有多个收藏
db.songList.userA.find()
"title": "Some song of user A", "artist": "Some artist of user A"
db.songList.userB.find()
"title": "Some song of user B", "artist": "Some artist of user B"
优点
要查询的集合大小更小
缺点
可维护性
1000 个用户意味着 1000 个集合
与拥有“用户”字段的单个集合相比
db.songList.find("user":"A")
"title": "Some song of user A", "artist": "Some artist of user A", "user": "A"
优点
如有需要,可灵活地跨用户查询
缺点
性能
我正在尝试建立一个赞成/反对名单,但仍然在围栏上。鉴于每个用户的歌曲将彼此隔离,哪种方法更好?我主要关心的是维护和查询性能。
提前致谢。
【问题讨论】:
与其担心这样的事情,不如构建something。您可能会通过构建它来找出最有效的方法,而不必担心细节。 同意@SomeKittens。也就是说,我会为每个用户做这件事,因为更容易犯错误并向 B 展示 A 的歌曲。无论如何,如果/当我有足够的用户时,我会担心优化。 安全方面,每个用户拥有一个集合可以使用 Mongodb 的集合级访问控制机制。这样,可以在数据库级别确保一个用户永远不会访问另一个用户的数据。 @Steven 我很想知道你选择了哪种设计,因为我现在也面临着类似的困境。 【参考方案1】:我会推荐 NOT
为每个用户单独收集。
阅读documentation
默认情况下,MongoDB 的每个名称空间限制为大约 24,000 个 数据库。每个命名空间为 628 字节,.ns 文件为 16MB 默认。
每个集合都算作一个命名空间,每个索引也是如此。因此,如果 每个集合都有一个索引,我们最多可以创建 12,000 个 收藏品。 --nssize 参数允许您增加此限制 (见下文)。
请注意,每个集合都有一定的最低开销——a 几KB。此外,任何索引都需要至少 8KB 的数据空间,因为 b-tree 页面大小为 8KB。如果存在某些操作可能会变慢 有很多集合,元数据被分页。
因此,如果您的用户超出命名空间限制,您将无法正常处理它。此外,随着用户群的增长,它的性能也不会很高。
更新
正如@Henry Liu 在 cmets 中提到的那样。对于使用WiredTiger存储引擎的Mongodb 3.0或以上版本,不再是限制。
docs.mongodb.org/manual/reference/limits/#namespaces
【讨论】:
感谢您的信息,但阅读下一段描述了如何使用 --nssize 来提高此限制(最大 .ns 文件大小为 2GB)。因此,如果每个 songList 集合只有 1 个索引,理论上我可以在接近 2GB 之前拥有 240,000 多个集合。 (如果我每个集合有 2 个索引,这个限制几乎减半)。 您显然可以以任何您想要的方式建模。我所做的只是推荐一种优雅的方法:) 感谢您的意见非常有帮助,在阅读了此信息后,多个集合似乎没有必要,因为我可以在一个集合中做我需要的事情,同时避免命名空间限制。 从 mongodb 3.0 或更高版本开始,如果使用 WiredTiger 存储引擎,将不再是限制。 docs.mongodb.org/manual/reference/limits/#namespaces 感谢@HenryLiu 我早在 2012 年就写了答案。感谢您更新信息。我已在答案中添加了更新。【参考方案2】:MongoDB 擅长水平扩展。它可以跨动态集群对集合进行分片,以生成快速、可查询的数据集合。
因此,拥有较小的集合大小并不是真正的专家,我不确定这个理论来自哪里,它不在 SQL 中,也不在 MongoDB 中。分片的性能,如果做得好,应该与查询单个小数据集合的性能相关(开销很小)。如果不是,那么您的分片设置错误。
MongoDB 不擅长垂直扩展,正如@Sushant 引用的那样,MongoDB 的 ns 大小将是一个严重的限制。引用没有提到的一件事是索引大小和计数也会影响 ns 大小,因此它描述了这一点:
因此,如果每个集合都有一个索引,我们最多可以创建 12,000 个集合。 --nssize 参数允许您增加此限制(见下文)。
【讨论】:
我读过this,这让我相信我会看到多个较小集合的显着性能提升。你是说如果我在用户字段上有一个带有分片键的集合,我应该会看到类似的性能提升? 那里有太多未知数,无法准确说明他为什么得到这些时间,查询时间非常依赖于硬件、索引、数据、规范化等。但是他确实注意到当他查询时查询速度很快有大量记录,问题是当他在他的索引中使用少量选择性(价格> 100的少量类型记录),这让我相信他的索引不适合他的查询。跨度> 是的,像 user_id 这样的分片键(这里有点猜测,你真的应该真的为你的数据研究这个)将为包含 user_id 的查询产生不错的回报。然而,这并不是分片的全貌,我强烈建议您在此处和谷歌上进行一些搜索,然后立即认为 user_id 将解决您的分片问题。 感谢您的意见非常有帮助,如果我需要在实现单个集合后优化查询性能,我会做更多的研究并尝试使用分片。以上是关于MongoDB 结构:单个集合与多个较小的集合的主要内容,如果未能解决你的问题,请参考以下文章
如何从 MongoDB 中具有多个集合的数据库中访问单个集合数据