Как получить огромный размер данных эффективно? - PullRequest
2 голосов
/ 17 февраля 2020

У меня есть конечная точка API, которую я перепроектировал. Я использую его для поиска имени, и он возвращает не более 100 объектов за один запрос. Но есть около 1,3 млн. Таких объектов, которые я хочу получить.

Вот пример сущности из ответа:

{
 "name":"COMPANY NAME",
 "regNo":"100-H",
 "newRegNo":"191101000018",
 "type":"Company"
}

Я могу выполнить поиск либо по name, либо по regNo. нет минимального ограничения на количество символов для поиска. Я думал о поиске по алфавиту, но так как он возвращает не более 100 объектов одновременно, я не могу получить остальные. Итак, я попытался получить его по regNo. regNo может быть от 1 до 1000000.

вот сценарий, который я написал для извлечения всех сущностей по их regNo:

const test = async () => {
  const data = {};
  try {
    const requests = [];
    // since it returns no more than 100 entities at once it adds 100 
    // to the search query on every loop

    for (let i = 100; i < 10000; i += 100) {
      requests.push(fetchData(i));
    }
    const result = await Promise.all(requests);

    result.forEach(res => {
      res.entityList.forEach(entity => {
        data[entity.regNo] = entity;
      });
    });

    // You can ignore this part
    fs.writeFile("data.json", JSON.stringify(data), err => {
      console.log(err);
    });
    console.log(Object.keys(data).length);
  } catch (err) {
    console.log(err);
  }
};

Потребовалось около 15 секунд, чтобы получить 9100 объекты (сделано 100 циклов) И каждый regNo имеет суффикс из одной буквы, например: 11000-H

Если я получу 100, он вернет что-то вроде этого:

entityList: [
    {
      name: "COMPANY NAME",
      regNo: '100-H',
      newRegNo: '191101000018',
      type: 'Company'
    },
    {
      name: "COMPANY NAME",
      regNo: '1000-V',
      newRegNo: '193901000021',
      type: 'Company'
    },
    {
      name: "COMPANY NAME",
      regNo: '10000-T',
      newRegNo: '197001000604',
      type: 'Company'
    },
    {
      name: "COMPANY NAME",
      regNo: '100000-D',
      newRegNo: '198301004377',
      type: 'Company'
    },
    {
      name: "COMPANY NAME",
      regNo: '1000001-W',
      newRegNo: '201001012078',
      type: 'Company'
    },
    {
      name: "COMPANY NAME",
      regNo: '1000002-K',
      newRegNo: null,
      type: 'Company'
    },
    {
      name: "COMPANY NAME",
      regNo: '1000003-U',
      newRegNo: '201001012079',
      type: 'Company'
    },
    {
      name: "COMPANY NAME",
      regNo: '1000004-V',
      newRegNo: '201001012080',
      type: 'Company'
    },
    {
      name: "COMPANY NAME",
      regNo: '1000005-D',
      newRegNo: '201001012081',
      type: 'Company'
    },
    {
      name: "COMPANY NAME",
      regNo: '1000006-A',
      newRegNo: '201001012082',
      type: 'Company'
    },
 .......

Как вы можете видеть он не возвращает сущности от 0 до 99. Я предполагаю, что самый высокий regNo равен 1000000-suffixLetter, и если я смогу получить от 100 до 1000000 за все oop, я бы выбрал около 1M сущностей. НО вот трюк regNo имеет букву суффикса. Давайте предположим, что если я получу 100, он вернется с 100-A до 199-A. Но есть и другие сущности, такие как 100-B, 100-C, et c

, как я могу эффективно извлечь 1,3M + сущности без потери данных?

1 Ответ

0 голосов
/ 17 февраля 2020

ОК, похоже, что вы просматриваете около 250 МБ данных, и обратные циклы запроса занимают около 15 мс. Предполагая, что у вас есть скорость загрузки 100 Мбит / с, теоретическая максимальная скорость, с которой вы можете сделать это, составляет 20 секунд.

Поскольку большую часть времени, которое здесь происходит, кажется, ожидает сетевых обходов, вы можете попытаться массово распараллелить это. Вместо зацикливания одного потока вы можете l oop и создавать много потоков. До некоторой степени, я ожидал бы, что вы получите почти пропорциональное ускорение от этого, так как у вас здесь почти нет времени вычислений, почти исключительно ввода / вывода. После этого вы можете начать исчерпывать доступные сетевые ресурсы и снова оказаться узким местом. Однако ваша система должна быть способна обрабатывать много независимых запросов одновременно.

Принимая во внимание, что ваша однопоточная программа занимает ~ 15 мс на запрос, и потенциально есть ~ 1,3 млн запросов, вы будете рассматривать примерно 195 000 секунд работает таким образом. Используйте один другой поток, и я был бы удивлен, если бы вы не увидели что-то около 100 000 секунд. Используйте четыре темы, и вы можете получить около 50000 секунд. Возможно, вам придется поэкспериментировать с меньшим диапазоном и переключать количество потоков, пока не увидите максимальную пропускную способность.

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

...