node.js - Nodejs Mongodb 发现性能问题
问题描述
我最近刚接触 mongodb,到那时我遇到了很多问题。我正在创建一个纸牌游戏,所以我认为 mongodb 将是最好的选择。
现在我正试图找到我所有的牌组、手牌和桌牌,问题是它需要很长时间才能执行,即使收集量很小。
例如
{"_id":"5bd3323b1431aa01eed604a8","userID":1,"handData":[{"id":"MLTOG","suit":"Spades","value":5,"face":"5","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"3ZgGQ","suit":"Spades","value":3,"face":"3","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"zdgyN","suit":"Clubs","value":2,"face":"2","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"oy4CS","suit":"Spades","value":4,"face":"4","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"PgTxA","suit":"Diamonds","value":3,"face":"3","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"zlx6Y","suit":"Diamonds","value":4,"face":"4","userHide":false,"globalHide":false,"hasSuperPower":false}]}
{"_id":"5bd3315f11716c01d3a5a4a4","gameID":"aasd12","deckData":[{"id":"rPd2D","suit":"Diamonds","value":7,"face":"7","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"ZslMO","suit":"Hearts","value":14,"face":"Ace","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"vJ4j2","suit":"Hearts","value":13,"face":"King","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"sQWuO","suit":"Clubs","value":12,"face":"Queen","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"SV6wb","suit":"Clubs","value":4,"face":"4","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"XGut7","suit":"Hearts","value":4,"face":"4","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"jmiM8","suit":"Hearts","value":3,"face":"3","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"BqQgl","suit":"Hearts","value":7,"face":"7","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"1sDky","suit":"Hearts","value":6,"face":"6","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"PWTot","suit":"Spades","value":12,"face":"Queen","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"ctBqJ","suit":"Spades","value":10,"face":"10","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"g7MX1","suit":"Clubs","value":7,"face":"7","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"voGO8","suit":"Hearts","value":5,"face":"5","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"SeOwQ","suit":"Spades","value":14,"face":"Ace","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"67eKt","suit":"Clubs","value":11,"face":"Jack","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"rBfas","suit":"Spades","value":13,"face":"King","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"xD5X6","suit":"Clubs","value":14,"face":"Ace","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"91yRB","suit":"Diamonds","value":11,"face":"Jack","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"TMbbQ","suit":"Spades","value":7,"face":"7","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"6NQvl","suit":"Diamonds","value":5,"face":"5","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"0pMrB","suit":"Clubs","value":10,"face":"10","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"zIMFm","suit":"Hearts","value":12,"face":"Queen","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"KeQNt","suit":"Hearts","value":8,"face":"8","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"KSxvM","suit":"Clubs","value":8,"face":"8","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"MaNEM","suit":"Clubs","value":5,"face":"5","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"jU2h3","suit":"Hearts","value":10,"face":"10","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"VqKOQ","suit":"Diamonds","value":9,"face":"9","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"S0dz2","suit":"Spades","value":2,"face":"2","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"ehIbj","suit":"Spades","value":6,"face":"6","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"VsDTD","suit":"Diamonds","value":13,"face":"King","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"tmzY9","suit":"Clubs","value":3,"face":"3","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"eSQ8n","suit":"Hearts","value":2,"face":"2","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"y3fEo","suit":"Clubs","value":9,"face":"9","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"m5EBi","suit":"Diamonds","value":14,"face":"Ace","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"4IFqQ","suit":"Diamonds","value":10,"face":"10","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"KlGhF","suit":"Spades","value":8,"face":"8","userHide":false,"globalHide":false,"hasSuperPower":true},{"id":"wsLfO","suit":"Diamonds","value":12,"face":"Queen","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"9O44l","suit":"Hearts","value":11,"face":"Jack","userHide":false,"globalHide":false,"hasSuperPower":false},{"id":"H0r9u","suit":"Diamonds","value":6,"face":"6","userHide":false,"globalHide":false,"hasSuperPower":false}]}
fetch函数是这样的,当然mongoClient连接不是办法,我只是用这个函数来测试。
const getDeckCards = (gameid) =>{
return new Promise ((resolve,reject) => {
console.time("deck");
MongoClient.connect(url, { useNewUrlParser: true }, function (err, client) {
const db = client.db(dbName);
const collection = db.collection("deck");
resolve(collection.find({ gameID: gameid }).project({ _id: 0, gameID: 0 }).toArray());
});
console.timeEnd("deck");
});
}
const getHandCards = (userid) =>{
return new Promise ((resolve,reject) => {
console.time("hand");
MongoClient.connect(url, { useNewUrlParser: true }, function (err, client) {
const db = client.db(dbName);
const collection = db.collection("hand");
resolve(collection.find({ userID: userid }).project({ _id: 0, userID: 0 }).toArray());
});
console.timeEnd("hand");
});
}
const getTableCards = (gameid) =>{
return new Promise ((resolve,reject) => {
console.time("table");
MongoClient.connect(url, { useNewUrlParser: true }, function (err, client) {
const db = client.db(dbName);
const collection = db.collection("table");
resolve(collection.find({ gameID: gameid }).project({ _id: 0, gameID: 0 }).toArray());
});
console.timeEnd("table");
});
}
我尝试获得所有承诺,然后将它们作为数组返回。
const initGame = (async() => {
console.time("init");
let [deck,hand,table] = await Promise.all([
getDeckCards("aasd12"),
getHandCards(1),
getTableCards("aasd12")
])
console.timeEnd("init");
return [deck[0],hand[0],table[0]];
});
它表明,deck、hand、table 函数非常快,这是我希望得到的结果,但整个结果需要 1 秒,这对于如此小的查询来说非常慢
deck: 12.235ms
hand: 1.977ms
table: 0.534ms
init: 1058.646ms
我做错了什么?是承诺所有功能需要很长时间才能执行还是我的 Mongodb 查询有问题?
解决方案
问题是您每次都创建一个到 mongo 的新连接。
解决方案是创建一个连接并保持它处于活动状态并在不再需要时关闭它(当应用程序停止时)。
此示例代码肯定会对您的性能产生很好的影响:
class GameManager {
constructor() {
this.mongoClient = null;
}
async connect(dbName) {
this.mongoClient = await MongoClient.connect(url, { useNewUrlParser: true });
this.db = this.mongoClient.db(dbName);
}
getDeckCards(gameId) {
if (!this.mongoClient) {
return Promise.reject();
}
return this.db.collection("deck")
.find({ gameID: gameId })
.project({ _id: 0, gameID: 0 })
.toArray();
}
}
const initGame = () => {
console.time("init");
const gameManager = new GameManager();
return gameManager.connect(dbName)
.then(() => {
return Promise.all([
getDeckCards("aasd12"),
getHandCards(1),
getTableCards("aasd12")
])
})
.then(() => {
console.timeEnd("init");
});
};
还要记住在您搜索的那些字段上在 mongo 上创建索引(例如gameID
在这种情况下)。通过这种管理,您可以更快地访问数据。
推荐阅读
- android - 文本输入布局设计有问题?
- c++ - 几次迭代后,循环输出“Killed”中的重用向量
- java - 关于 Elasticsearch 架构和查询的问题
- sql - 如何在 SQL 中将 varchar2 转换为数字
- sql - 从 SQLite 数据库中获取时尝试/除了不工作
- c - 在函数中引用指针有什么区别
- ios - 如何在 Swift 中使用共享容器/应用程序组从其他目标访问文件
- tensorflow - keras.utils.Sequence 与多个文件
- python - 如何正确读取 csv 文件并返回数据以用于其他功能
- python - 尝试用树枝为不断增长和收缩的细丝设置动画