MongoDB查询从Heroku上的Node.js应用程序花费2-3秒

我在MongoDB上遇到主要的性能问题。在少于100个文档的数据库中,简单的find()查询有时需要2,000-3,000毫秒才能完成。

我在MongoDB Atlas M10实例和在Digital Ocean上具有4GB RAM的VM上设置的群集中都看到了这一点。当我在Heroku上重新启动Node.js应用程序时,查询在10到15分钟内表现良好(不到100毫秒),但是随后它们变慢了。

我是错误地连接到MongoDB还是从Node.js错误地查询?请在下面查看我的应用程序代码。还是在共享VM环境中缺少硬件资源?

任何帮助将不胜感激。我已经使用Explain查询和Mongo Shell完成了所有的疑难解答。

var Koa = require('koa'); //v2.4.1
var Router = require('koa-router'); //v7.3.0

var MongoClient = require('mongodb').MongoClient; //v3.1.3

var app = new Koa();
var router = new Router();

app.use(router.routes());

//Connect to MongoDB
async function connect() {
    try {
        var client = await MongoClient.connect(process.env.MONGODB_URI, {
            readConcern: { level: 'local' } 
        });
        var db = client.db(process.env.MONGODB_DATABASE);

        return db;
    }
    catch (error) {
        console.log(error);
    }
}

//Add MongoDB to Koa's ctx object
connect().then(db => {
    app.context.db = db;
});

//Get company's collection in MongoDB
router.get('/documents/:collection', async (ctx) => {
    try {
        var query = { company_id: ctx.state.session.company_id }; 

        var res = await ctx.db.collection(ctx.params.collection).find(query).toArray();

        ctx.body = { ok: true, docs: res };
    }
    catch (error) {
        ctx.status = 500;
        ctx.body = { ok: false };
    }
});

app.listen(process.env.PORT || 3000);

更新

我正在使用MongoDB变更流和标准的“服务器已发送事件”向应用程序UI提供实时更新。我关闭了这些功能,现在MongoDB似乎再次表现良好。

是否已知MongoDB变更流会影响读/写性能?

Mandy村村2020/04/03 11:00:49

我建议您做更多的日志工作。重新启动一段时间后,缓慢的查询可能比您想象的要糟糕。

对于在普通计算机上运行的现代数据库/ Web应用程序,如果操作正确,则很难遇到性能问题。可能存在内存泄漏或其他未释放的资源,或者网络拥塞。

恕我直言,您可能想先确定是否是网络问题,然后通过在MongoDB上启用慢速查询日志并在查询开始和结束的地方登录代码,可以实现此目的。

If the network is totally fine and you see no MongoDB slow queries, that means something goes wrong in your own application. Detailed logging might really help where query goes slow.

Hope this would help.

Mandy村村2020/04/03 11:00:49

变更流确实会影响服务器的性能。正如这个SO问题所指出的

正如那里接受的答案所述

MongoDB的Node.js客户端中默认连接池大小为5。由于每个更改流游标都会打开一个新连接,因此连接池至少必须与游标数一样大。

const mongoConnection = await MongoClient.connect(URL, {poolSize: 100});

(感谢MongoDB Inc.调查此问题。)

您需要增加池大小才能恢复正常性能。