TimeoutError при вставке jsons в базу данных Postgres - PullRequest
0 голосов
/ 12 февраля 2019

Я хочу вставить мои файлы в мою базу данных, которые включают в себя массивы объектов (строки).У меня около восьми тысяч файлов в 25 папках и около 40000 записей.

Я получаю TimeoutError: ResourceRequest истекло время ожидания.

Я пытаюсь увеличить время соединения для продолжения, но выдает ошибку после первой тысячи строк.Как правильно и эффективно вставить 40000 строк в мою локальную базу данных?

let folders_path = path.join(__dirname, "extracted_subjects/*");

function bulk_insert() {
  glob(folders_path, readFolders);
}

function readFolders(err, folders) {
  if (err) {
    console.log("ERROR readFolders: ", err);
    return;
  }
  folders.forEach(function(file) {
    glob(path.join(file, "/*.json"), readFiles);
  });
}
function readFiles(err, files) {
  if (err) {
    console.log("ERROR readFiles: ", err);
    return;
  }
  files.forEach(async function(fileName) {
    //console.log(fileName);
    let promise = getData(fileName, "utf8")
      .then(data => {
        try {
          // Parse And Bulk Create
          let obj = JSON.parse(data);
          models.dream
            .bulkCreate(obj)
            .then(function() {
              console.log("File: inserted!");
            })
            .catch(err => console.log("Error", err));
        } catch (SyntaxError) {
          console.log("File: ", fileName);
          return;
        }
      })
      .catch(err => console.log(err));

    await promise;
  });
}

function getData(fileName, type) {
  return new Promise(function(resolve, reject) {
    fs.readFile(fileName, type, (err, data) => {
      err ? reject(err) : resolve(data);
    });
  });
}

1 Ответ

0 голосов
/ 12 февраля 2019

Вы можете увеличить настройки по умолчанию для вашего соединения, например (вы можете прочитать о них в документации):

    dialectOptions:   {
      timeout: 30
    },
    operatorsAliases: Sequelize.Op,
    pool:             {
      max:            5,
      min:            0,
      idle:           30000,
      maxConnections: 5,
      maxIdleTime:    30
    },

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

Я подозреваю, что это поведение не то, что вы хотели написать

files.forEach(async function (fileName) {
  let promise = getData(fileName, 'utf8');
    // ...
  await promise;
});

Эта часть кода использует слова async и await, это не делает их последовательным чтением, они все еще могут работать параллельно.Вы собираетесь вызвать функцию getData как можно быстрее, а затем начать бомбардировку models.dream.bulkCreate.Использование bulkCreate здесь также не имеет смысла, так как вы ничего не создаете массово, скорее один за другим

опции, которые я мог бы увидеть для этого:

a) сохранить подобный код,но перебирайте файлы 25 на 25 параллельно с одной записью на блок, это изменение немного больше, читайте 25 в памяти, записывайте их в базу данных, читайте следующие 25 и т. д.
б) сохраняйте похожий код, нопереходите к файлам 25 на 25 параллельно с 25 записями на блок, это изменение немного больше, открывайте и читайте 25 файлов, а затем для каждого пишите только одну строку, затем переходите к
c) сохраняйте аналогичный код, но вместочитая каждый файл и записывая его в базу данных, держите их в памяти и запишите все данные только один раз в конце, как только у вас будут все данные.однако в вашем случае с этими большими данными у вас может не хватить памяти
d) если производительность не является проблемой, так как вы хотите / должны сделать это один раз (через некоторое время), вы можете просто перебрать всефайлы и считывайте их в режиме синхронизации, так что он всегда будет идти один за другим.

files.forEach(async function (fileName) {
  let data = fs.readFileSync(fileName, 'utf8'); // read the file sync

  try {
    let parsedData = JSON.parse(data); // try parsing
    models.dream                       // and inserting 
      .create(parsedData)              // this should not be bulkCreate, right??
       // this is kinda wrong, it doesn't automatically mean it 
       // is inserted, but it is copy paste from above
      .then(res => console.log('File: inserted!')) 
      .catch(err => console.log('Error', err));
  } catch (SyntaxError) {console.log('File: ', fileName);}
};

Что делает этот фрагмент кода, так это удостоверяется, что вы действительно последовательно переходите от файла к файлу, это замедлит выполнениезначительно для вашей стороны, но так как вы изначально заявили, что хотите сделать это на своем локальном хосте, я предполагаю, что у вас есть время, чтобы оставить его работающимВы все еще рискуете, что вы можете читать файлы быстрее, чем база данных может справиться с их записью, но это время не должно сильно отличаться от синхронизированного чтения следующего файла, и ваша система должна быть в состоянии поддерживать скорость, особенно если вы увеличиваете количество разрешенныхсоединение в вашем пуле.

Для производства я бы, вероятно, выбрал варианты a или b, в зависимости от того, знал ли я заранее максимальный размер / количество файлов.

...