我的应用程序中使用mongodb驱动程序(最新版本)的db.collection.find非常慢。我对其中一个做了如下调查
// about 300 hundred ids at a time (i've tried lower and higher numbers - no impact
db.users.find({_id : {$in : [1,2,3,4,5,6....]}}) 一旦我得到游标,我就做:cursor.toArray(),然后迭代结果
toArray操作非常慢。平均要花一分钟。重要:我的数据库在任何时候都处于非常沉重的负荷之下。这个特别的收藏有超过50毫米的条目。
我已经将mongo驱动程序的问题缩小到了com.mongodb.Response --特别是这一行:
final byte [] b = new byte[36];
Bits.readFully(in, b);令人难以置信的是,只有36个字节的readFully占用超过一分钟的时间!
当我给数据库带来负担时,改进是很大的。从一分钟到五到六秒。我的意思是5-6秒得到300个文件仍然是超级慢,但绝对比1分钟更好。
我能做些什么来进一步解决这个问题呢?是否需要查看MondoDB上的设置?
发布于 2014-08-12 09:15:45
会发生什么?
您正在加载所有300个用户文档。
所发生的情况是搜索_id索引,并将相应的文档完全发送到应用程序。因此,mongoDB将访问它的数据文件,读取第一个文档并将其发送给您,然后跳转到下一个文档并发送给您等等。如果使用游标,则在返回与定义的游标大小相等的多个文档后,就可以开始迭代返回的文档,因为其他文档将在需要时从服务器上的游标中延迟加载。(有点简单化,但足以回答这个问题)。您要做的是显式地等待索引被扫描,文档被定位,发送回应用程序,并一直到最后一个文档的最后一个字节。正如@wdberkeley (为10™工作)正确指出的那样,这是一个非常糟糕的想法,™。
是什么导致或加剧了这个问题?
在沉重的负荷下,可能会发生两件事。更有可能的是,您的_id索引不再存在于内存中,这将导致数千(如果不是数百万)从磁盘读取-这是缓慢的。如果索引保存在RAM中,则要慢得多(按几个数量级)。因此,导致延迟的不是您提到的代码片段,而是MongoDB的响应时间。在负载较重的情况下,另一个选项是磁盘IO太低,或者(更可能)随机文件读取延迟太高。我假设您使用的是旋转磁盘加上不够大小的数据库内存。
怎样才能找到原因
db.users.stats()找出索引大小。我很确定您的索引大小(s加起来)超过了可用RAM。如何解决这个问题?
如果您没有足够的RAM,要么放大,要么缩小。
如果您的磁盘延迟或吞吐量太高,则可以使用SSD来存储MongoDB的数据,或者使用SSD来存储MongoDB的数据。
使用游标对象对文档进行迭代。在我能想到的几乎每个用例中,这都是一个更好的解决方案。
发布于 2018-09-07 07:32:08
将MongoDB驱动程序升级到3.6.4将在不需要时间的情况下获取数据。我们收集了大约200万份文档,以前的版本大约需要3分钟,但升级到3.6.4之后,只需5-7 sec.So,我就感觉到旧版本的mongoDB驱动程序存在一些问题。
https://stackoverflow.com/questions/25244988
复制相似问题