MongoDB在内存中缓存集合吗?

3

我正在使用 mongoDB 存储多边形的集合,并使用 $geoIntersects 查询来查找特定点在哪个多边形中。

我的 mongoose Schema 如下所示:

var LocationShema = mongoose.Schema({
    name: String,
    geo: {
        type: {
            type: String 
        },
        coordinates: []
    }
});

LocationShema.index({geo: '2dsphere'});

module.exports = mongoose.model('Location', LocationShema);

所以,每个元素都是一个多边形。我添加了2dsphere索引,希望查询速度更快,并且整个集合存储在内存中。不幸的是,对于我的用例,大约20个查询需要花费600毫秒,这太长了。

我的查询看起来像这样:

Location.find({
            geo: {
                $geoIntersects: {
                    $geometry: {
                        type: 'Point',
                        coordinates: [pos.lng, pos.lat]
                    }
                }
            }
 },...)

有没有办法让这个运行更快?我能否强制MongoDB将整个集合缓存在数据库中(因为该集合从不改变)?有没有办法检查集合是否实际存储在内存缓存中

此外,是否有任何替代方案可供使用(例如:库或其他东西),可以实现快速地地理空间查询?


1
你可以发布一个查询的 explain() 吗? - KRONWALLED
在Mongo shell中执行查询时,请使用“db.collectionName.find(query).explain()”。 - profesor79
1
你是如何运行这20个查询的?并发还是顺序执行?它们可以合并成一个查询吗? - robertklep
尝试同时运行它们。 - robertklep
@robertklep,目前为止,我通过线性搜索每个点的所有多边形(因此没有任何MongoDB地理空间查询)将时间从600ms减少到150ms。 我认为只要多边形的数量不超过200个左右(目前有100个多边形),线性搜索总是比查询更快。 - XCS
显示剩余5条评论
2个回答

2

使用 mongo >3.0 版本,可以使用内存存储,这意味着当种子集合留在内存中时,您可以拥有 mongo 实例(所有更改不会持久化)。

另一方面,如果您的集合是静态的,可以通过实现缓存存储(如 Redis),或者使用带有存储查询和响应的 TTL 索引集合来解决。

播种过程可以通过当前集合的备份和恢复到内存集合来完成。

当频繁地查询集合时,在繁忙系统上,它将保留在内存中,只要mongo需要加载其他集合即可。

欢迎任何评论!


那么,我可以只为这个集合使用inMemory存储吗?我该如何给这个集合"种子"数据呢? - XCS
1
我期望在查询运行一次后,相关的磁盘块将存在于操作系统的磁盘缓冲区中(前提是有足够的可用内存)。 - robertklep

0

你不能将特定的集合保留在内存中,而将其他集合保存到磁盘上,但请记住,当您多次执行相同的查询时,mongodb 在内部进行了一些缓存。

以下是您可以做的:

  • 选项1:您可以使用$merge$out创建一个“视图”,并使用find(all)查询此集合。顺便说一句,有时候最好进行全面扫描,而不是按索引进行(如果您有许多结果,特别是如果每个文档的大小都很大)。因此,使用“视图”时,您可以不使用任何索引-因为您进行了全部查找-并且更有可能缓存结果。这也涉及到您的 RAM 有多大,因为也许 mongodb 需要在 RAM 中交换数据
  • 选项2:如果您的数据是只读的,则可以完全将 mongodb 加载到内存中(https://docs.mongodb.com/manual/core/inmemory/),仅具有此集合。但是,您必须找到一种方法,在 mongodb 重新启动时再次创建和填充集合。

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