数据库中集合数量的限制

54
有没有任何关于mongodb集合数量的实际限制呢? 在这里https://docs.mongodb.com/manual/core/data-model-operations/#large-number-of-collections中写到:

通常,拥有大量集合不会对性能造成显著影响,反而会导致非常好的性能。

但出于某种原因,mongodb将数据库中的命名空间数量限制为24000个。看起来它可以增加,但是如果在数据库中有很多集合不会引起任何性能损失,那么为什么在默认配置中还有这样的限制呢?

这是否意味着在一个数据库中拥有实际上无限数量的集合是可行的,例如,在一个多租户应用程序的数据库中,拥有一个帐户数据集合,该数据库中有数十万个集合? 如果为每个租户在数据库中拥有非常大数量的集合是可行的解决方案,那么与在一个集合中为每个租户拥有文档相比,它有什么好处? 非常感谢您的回答。


1
答案很有信息量,但由于这是未来的问题,我要补充一下:文档现在说明了从3.2版本开始默认的Wired Tiger不受此限制。文档链接 - WAF
尽管WiredTiger没有这样的限制,但我发现拥有数千个集合会导致启动服务器时出现问题。它使用大量的RAM并打开指向磁盘上每个*.wt文件的指针。资源消耗最终会稳定下来以达到正常操作使用,但我的重新启动需要10分钟,并且我必须租用具有多倍于我实际需要的RAM的服务器。现在建议大量集合是一种反模式。所谓“巨大”就这样了。 - Tim
6个回答

40
这个回答有点晚了,但其他答案在可靠性和事实信息方面似乎有些不足,所以我会尝试稍微纠正一下。
但出于某种原因,mongodb将数据库中的名称空间数量限制为24000,这仅仅是默认设置。是的,有一个默认设置。
它确实在限制页面上说24000是限制 (http://docs.mongodb.org/manual/reference/limits/#Number%20of%20Namespaces),好像没有办法扩展,但实际上是可以的。
但是,对于命名空间文件的大小有最大限制 ( http://docs.mongodb.org/manual/reference/limits/#Size%20of%20Namespace%20File ),即2GB。在大多数情况下,这给您提供了大约300万个命名空间可供使用,这相当令人印象深刻,我不确定有多少人会很快达到这个限制。

您可以使用nssize参数修改默认值,使其高于16MB。您可以在配置文件中 (http://docs.mongodb.org/manual/reference/configuration-options/#nssize) 或运行MongoDB时通过操作命令 (http://docs.mongodb.org/manual/reference/mongod/#cmdoption-mongod--nssize) 来实现。

据我所知,MongoDB默认将nssize设置为16MB并没有真正的原因。我从未听说过“不要打扰用户”的座右铭,因此我不相信这个理由。

我认为,MongoDB隐藏这个设置的主要原因是,尽管文档中指出:

对于高吞吐量的批处理,不同的集合非常重要。

但使用多个集合作为垂直扩展的手段而不是像MongoDB设计的那样水平扩展集群,在大型网站上通常被认为是不良做法。因此,12K个集合通常被认为是人们永远不会、也不应该达到的数量。


是否可以从每个集合中获取记录,例如如果我有user.primary和user.secondary在这些集合中,我能否一次选择两个集合中的用户名称? - jackyesind
@jackyesind 不,MongoDB 命令只适用于单个集合,而且没有服务器端的 JOIN 操作。 - Sammaye
@UpTheCreek 说实话,那是引用了一位10gen工程师的话,我从未真正计算过。 - Sammaye
谢谢 - 是的,我的计算出了错误。 - UpTheCreek
如果您使用WiredTiger,则没有集合数量限制。现在WiredTiger是默认引擎,因此可以放心地说不再有集合数量限制了。 - Fred
显示剩余3条评论

23

没有更多限制!

正如其他答案所述 - 这取决于命名空间文件的大小。以前这是一个问题,因为它具有默认限制为16mb和最大2gb的限制。但是,随着MongoDB 3.0和WiredTiger存储引擎的发布,看起来此限制已被删除。WiredTiger在几乎所有方面似乎都更好,因此我认为除了遗留支持原因外,没有人使用旧引擎的理由。从该网站上可以看到:

对于MMAPv1存储引擎,命名空间文件的大小不能超过2047兆字节。

默认情况下,命名空间文件为16兆字节。您可以使用nsSize选项配置大小。

WiredTiger存储引擎不受此限制。

http://docs.mongodb.org/manual/reference/limits/


14

一些背景信息:

每次MongoDB创建一个数据库时,它都会为其创建一个命名空间(db.ns)文件。该命名空间文件保存有关集合的元数据。默认情况下,命名空间文件的大小为16MB,但是您可以手动增加其大小。每个集合的元数据大约为648字节加上一些开销字节。将其除以16MB,您将得到每个数据库大约24000个命名空间。您可以通过指定更大的命名空间文件来启动MongoDB,这将允许您在单个数据库中创建更多的集合。

任何默认配置的想法都是不要打扰用户去处理每个细节(和可配置的旋钮),而是选择通常适用于大多数人的一个配置。此外,可行性确实与最佳/良好的设计实践密切相关。正如Chris所说,请考虑您的数据形状并相应地做出决策。


2
问题是为什么他们要设置这个限制。他们是否认为在某些数量的命名空间中,我们可能会遇到性能问题? - Oleg
我不确定为什么你把它看作是一个限制。这只是一个默认值,其想法是它适合大多数人的用例。如果您的用例需要更多的集合,没有任何东西会阻止您创建一个更大的命名空间文件。 - Sid
2
在我看来,如果命名空间的数量可以无限制,就不需要为其设置任何参数,从而允许拥有无限数量的命名空间。即使我增加了限制,可能会在某个时候仍然存在达到限制的问题,对吗? - Oleg
1
我知道我来讨论已经很晚了,但在我看来,像你所建议的这样一个开放式版本需要额外的功能,即命名空间文件必须能够根据需求自动扩大。如果你想在那个地方保持简单,你可以选择一个固定的限制,希望一旦人们需要超越这个限制,他们就已经进步到知道该转哪个轮子的程度了。 - Nicolas78

4

如其他人所提到的,默认命名空间大小为16MB,您可以获得约24000个命名空间条目。实际上,我的Ubuntu 64位实例在使用默认的16MB命名空间文件时达到了23684个。

一个FAQ中未提及但很重要的事情是索引也使用命名空间槽。

您可以使用以下命令统计命名空间条目:

db.system.namespaces.count()

同时,实际查看其中的内容也很有趣:

db.system.namespaces.find()

将限制设置得比您认为需要的更高,因为一旦创建了数据库,命名空间文件就无法扩展(据我所知——如果有方法,请告诉我!)。


默认情况下,命名空间文件大小为16兆字节。您可以使用nssize选项配置大小。 - Cooper.Wu
2
您只能在创建数据库之前配置命名空间的大小。要更改它,您需要执行mongodump,销毁数据库,重新配置mongod,重新启动并使用mongoload加载。或者可以使用较大的nssize选项添加其他副本,然后再将较小的nssize替换为旧的副本。 - Matt Connolly

3

维护集合似乎存在大量开销。我刚刚将一个有大约150万篇文档分布在11000个集合中的数据库缩减到一个拥有相同数量文档但只有约300个集合的数据库;这将数据库大小从8GB缩减到1GB。我不太熟悉MongoDB的内部工作原理,所以这可能是显而易见的,但我认为在这种情况下值得注意。


这取决于您使用的Mongo版本,切换到最新版本,然后测试相同的内容。 - saad

3
实际上,我从未遇到过最大值。但是除了在性能测试时,我肯定从未超过24,000个集合限制。我很确定除了那次之外,我从未超过200个。我必须承认,我认为在单个数据库中拥有那么多集合听起来像是一场可怕的混乱,而不是将类似的数据分组到它们自己的集合中。
考虑您的数据形状和业务规则。如果您的数据需要以不同的逻辑分组方式布置,以满足您的多租户应用程序的需求,那么您可能应该考虑其他数据存储。因为尽管Mongo很棒,但他们对集合数量设置了限制,这告诉我他们知道某些理论限制会影响性能。
也许您应该考虑与数据形状相匹配的存储方式?例如,Riak具有无限数量的“桶”(没有理论最大值),您可以在应用程序中拥有一个帐户一个桶。但是,采用这种方法会牺牲一些查询能力。
否则,您可能希望按照更关联的模型进行分组。在我看来,Mongo感觉像是关系数据库和键值存储之间的折衷点。这意味着从关系数据库世界中进行概念化更容易。

请问你能解释一下这里的意思吗:“我必须承认,我认为在单个数据库中拥有那么多集合听起来像是一种非常混乱的方式,而不是将类似的数据分组到它们自己的集合中。”?你所说的“将类似的数据分组到它们自己的集合中”是什么意思?你认为为每个租户使用一个集合会引起性能问题吗?如果每个数据都不超过N个集合且将其他租户存储在其他数据库中,会怎样呢? - Oleg
Riak 桶的一个问题是它有一个限制,大约只能存储 64M 的数据,而不像关系型数据库中的表和 MongoDB 中的集合可以存储任意数量的数据。 - Oleg
当我说“类似数据分组”时,我的意思是将具有相似字段的事物分组。假设您有一系列新闻通讯。您会将所有这些通讯归为同一集合,因为它们都是新闻通讯。即使它们不“配套”,因为它们可能适用于应用程序的不同租户。如果您熟悉关系建模,请朝着那个方向思考。 - Christopher WJ Rueber
关于Riak存储桶,你是从哪里听说的?每个存储桶中的条目最多允许100m(或类似的大小),但并不是每个存储桶都有这个限制。Mongo每个条目的限制是硬性的16m(当前版本)。从技术上来说,Riak在一个存储桶中存储的“文档”可以比Mongo集合中存储的每个“文档”容纳更多的数据。 - Christopher WJ Rueber
你的意思是说在Riak中,存储桶的大小没有限制,只有通过键存储的对象大小有限制? - Oleg
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接