Nodejs Mongodb обнаружил проблему с производительностью - PullRequest
0 голосов
/ 09 ноября 2018

Я только недавно положил руки на mongodb, к тому времени у меня было много проблем. Я создаю карточную игру, поэтому я подумал, что mongodb будет лучшим вариантом для этого.

Теперь я пытаюсь найти все свои колоды, руки и настольные карты, проблема в том, что выполнение занимает так много времени, даже если коллекция довольно мала.

* 1005 например *

{"_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}]}

Функции извлечения похожи на это, конечно, соединение с 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]];
  });

Это показывает, что функции колоды, руки, стола были довольно быстрыми, результат, который я надеюсь получить, но весь результат занимает 1 секунду, что невероятно медленно для таких маленьких запросов

deck: 12.235ms
hand: 1.977ms
table: 0.534ms
init: 1058.646ms

Что я делаю не так? Это функция обещания все, что выполняется слишком долго, или это проблема с моим запросом Mongodb?

1 Ответ

0 голосов
/ 09 ноября 2018

Проблема в том, что вы каждый раз создаете новое соединение с Монго.

Решение состоит в том, чтобы создать одно соединение, поддерживать его в рабочем состоянии и закрывать, когда оно больше не требуется (когда приложение останавливается).

Этот пример кода, безусловно, окажет хорошее влияние на вашу производительность:

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");
    });
};

Не забудьте также создавать ИНДЕКСЫ на монго для тех полей, которые вы ищете (например, gameID в данном случае). С помощью этого управления вы сможете быстрее получить доступ к данным.

...