问题描述
我正在使用“ MongoDB v4.2.x”。我的服务器内存仅为4GB,MongoDB的利用率超过60%。我正在运行简单的查询,甚至没有聚合,并且响应时间太慢。
问题:查询MongoDB数据库时如何减少内存消耗并改善响应时间?
到目前为止的想法:
-
MongoDB中是否有内存限制选项,以便可以将未使用的已加载数据库部分外包给磁盘?
-
更改“ wiredTiger”缓存的最大大小为1GB,但是响应时间仍然很慢。还有其他MongoDB调整吗?
-
Python是否有替代方法,而不是调整MongoDB本身?
解决方法
如果只想缩短响应时间并减少MongoDB占用的内存,一种解决方法是将MongoDB数据加载到pandas DataFrame中,这是两个选项,如下所示。
-
PyMongo的bson模块:如果确实只是连接到MongoDB的问题,则可以将数据库(或充其量您真正需要的部分)导出为bson文件,然后读取整个内容使用pymongo的bson.decode_all()将bson文件转换为一个pandas DataFrame。有关详细信息,请参见Read BSON file in Python?。
-
MongoDB集合:或者,如果您可能至少在开始时打开了MongoDB,则可以将MongoDB集合中的数据加载到pandas DataFrame中,请参见How can I load data from MongoDB collection into pandas' DataFrame?。加载后,关闭MongoDB以释放应用程序占用的内存。
在开始时加载数据库的额外时间为一次性费用。将整个数据库放在一个数据框中后,就可以使用Python查询该内存中的DataFrame。
如何减少Python的内存消耗和响应时间,
-
您可以在运行Python脚本期间释放内存,请参见How can I explicitly free memory in Python?,或覆盖对象。
-
避免不必要的对象复制,使用参数“ inplace”更改对象/自动分配更改的对象/使用.to_numpy(copy = False)/使用其他技巧来就地更改对象,即避免复制。
-
对于大规模操作,请尽可能将pandas对象转换为numpy对象。 Python是基于numpy构建的,并且在numpy上运行最快,pandas提供了更多(也更舒适)的选项,但开销更大。
-
选择df.apply()/ df.iterrows()的列表理解,请参见Dataframe list comprehension “zip(…)”: loop through chosen df columns efficiently with just a list of column name strings。
当您在DataFrame中拥有数据库时,您还需要考虑:
- MultiIndex(选中此nice guide),
- DatetimeIndex
- categorical data
- df.desribe() and stats.describe() for nested and unnested structures。
您可能想在宽格式和长格式之间切换:
- df.explode()/ df.groupby(有关此时间序列,请参见Convert pandas df with data in a "list column" into a time series in long format. Use three columns: [list of data] + [timestamp] + [duration])
- df.pivot与df.melt(= unpivot)。