Есть ли какое-то преимущество в стоимости Parse.Object.saveAll по сравнению с индивидуальным сохранением? - PullRequest
1 голос
/ 05 марта 2020

Parse JS SDK предоставляет метод Parse.Object.saveAll() для сохранения множества объектов одной командой.

При просмотре ParseServerRESTController.js кажется, что каждый объект сохраняется индивидуально:

if (path === '/batch') {
    let initialPromise = Promise.resolve();
    if (data.transaction === true) {
        initialPromise = config.database.createTransactionalSession();
    }
    return initialPromise.then(() => {
        const promises = data.requests.map(request => {
            return handleRequest(
                request.method,
                request.path,
                request.body,
                options,
                config
            ).then(
                response => {
                    return {
                        success: response
                    };
                },
                error => {
                    return {
                        error: {
                            code: error.code,
                            error: error.message
                        },
                    };
                }
            );
        });
        return Promise.all(promises).then(result => {
            if (data.transaction === true) {
                if (
                    result.find(resultItem => typeof resultItem.error === 'object')
                ) {
                    return config.database.abortTransactionalSession().then(() => {
                        return Promise.reject(result);
                    });
                } else {
                    return config.database.commitTransactionalSession().then(() => {
                        return result;
                    });
                }
            } else {
                return result;
            }
        });
    });
}

Кажется, что saveAll - это просто удобная оболочка для сохранения каждого объекта в отдельности, поэтому он все еще, кажется, делает n запросов к базе данных для n объектов.

Правильно, что saveAll не имеет никаких преимуществ с точки зрения затрат (производительность, сетевой трафик c и т. Д. c) по сравнению с сохранением каждого объекта индивидуально в облачном коде ?

1 Ответ

1 голос
/ 06 марта 2020

Я могу вам сказать, что ответ таков: Parse.Object.saveAll и Parse.Object.destroyAll пакетных запросов по по умолчанию в пакетах 20 объектов. Но почему поверьте мне на слово? Давайте проверим это!

Включите подробное ведение журнала, а затем выполните следующее:

const run = async function run() {
  const objects = [...Array(10).keys()].map(i => new Parse.Object('Test').set({i}));
  await Parse.Object.saveAll(objects);

  const promises = objects.map(o => o.increment('i').save());
  return Promise.all(promises);
};

run()
  .then(console.log)
  .catch(console.error);

А вот выходные данные из журналов сервера разбора (я обрезал это, но это должно достаточно, чтобы было ясно, что происходит):

verbose: REQUEST for [POST] /parse/batch: { // <--- note the path
  "requests": [ // <--- an array of requests!!!
    {
      "method": "POST",
      "body": {
        "i": 0
      },
      "path": "/parse/classes/Test"
    },

    ... skip the next 7, you get the idea

    {
      "method": "POST",
      "body": {
        "i": 9
      },
      "path": "/parse/classes/Test"
    }
  ]
} 
.... // <-- remove some irrelevent output for brevity.
verbose: RESPONSE from [POST] /parse/batch: { 
  "response": [
    {
      "success": {
        "objectId": "szVkuqURVq",
        "createdAt": "2020-03-05T21:25:44.487Z"
      }
    },
    ...
    {
      "success": {
        "objectId": "D18WB4Nsra",
        "createdAt": "2020-03-05T21:25:44.491Z"
      }
    }
  ]
} 
...

// now we iterate through and there's a request per object.
verbose: REQUEST for [PUT] /parse/classes/Test/szVkuqURVq: {
  "i": {
    "__op": "Increment",
    "amount": 1
  }
} 
...
verbose: REQUEST for [PUT] /parse/classes/Test/HtIqDIsrX3: {
  "i": {
    "__op": "Increment",
    "amount": 1
  }
} 
// and the responses...
verbose: RESPONSE from [PUT] /parse/classes/Test/szVkuqURVq: {
  "response": {
    "i": 1,
    "updatedAt": "2020-03-05T21:25:44.714Z"
  }
}
...

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

НО! вызовы между сервером синтаксического анализа и хранилищем данных обычно выполняются в очень быстрых сетях с использованием двоичного формата, тогда как вызовы между клиентом и сервером синтаксического анализа являются JSON и go на более длинные расстояния с обычно более медленными соединениями.

Есть еще одно потенциальное преимущество, которое вы можете увидеть в коде менеджера ядра, это то, что пакет выполняется в транзакции.

...