Почему Node JS убивает процесс при запросе к MySQL?

Совершаю запрос на получение данных из бд. Если запрашиваю небольшое количество данных, то все работает корректно. Но в БД ~7 млн. строк, и мне нужно получить все.

const mysql = require('mysql')

// создаем подключение
    const connection = mysql.createConnection({/*тут данные для входа*/})

    // подключаемся к БД
    connection.connect()

    // выполняем запрос
    connection.query("SELECT partname FROM `main`", (error, results, fields) => {
        if (error) throw error
    })

    // убиваем подключение к БД
    connection.end()


Процесс завершается с сообщением
Killed                                                                                                                                                     
npm ERR! code ELIFECYCLE
npm ERR! errno 137
. . .


С чем это может быть связано и как исправить?
  • Вопрос задан
  • 151 просмотр
Пригласить эксперта
Ответы на вопрос 1
neuotq
@neuotq
Прокрастинация
Ох.. ну вы даёте. У вас конечно же сыпется нода из-за ограничения оперативной памяти.
Делайте запросы кусками(чанками), можно начать с 1000.
(примерный полупсевдо код)
const mysql = require('mysql')

// создаем подключение, 
// используем https://github.com/mysqljs/mysql#pooling-connections читать настройку!
    const pool = mysql.createPool({/*тут данные для входа*/});
// Количество чанков
    const chunkSize = 1000;
//Запрос на количество строк в таблице
    const poolTableSizeQuery= "SELECT count(*) as rowsCount FROM main";
//Начинаем с определения количество строк
   pool.query(poolTableSizeQuery , function (error, results, fields) {
      if (error) throw error;    
      if (result && result[0]) {
    //Количество строк
      const rowsCount = result[0]['rowsCount']; 
   // Количество чанков размером в chunkSize (округляем значение)
      const chunksCount = Math.ceil(totalRows/chunkSize);
  // Наш запрос тепреь с ЛИМИТОМ
      const myQuery = "SELECT partname FROM `main` LIMIT";
      for(var i = 0; i < chunksCount; i++) {                 
               //Сдвиг для текущего чанка 
               let chunkOffset = i*chunkSize;
               //Сдвиг для текущего чанка
                let chunkQuery = myQuery + offset + "," + chunkSize;
               //Выполнение твоего запроса, уже с лимитом и сдвигом
                pool.query(chunkQuery , function (error, results, fields) {
                     if (error) throw error; 
                    //Тут выводим куда-то или ещё что.

                });
            }
     }
  });

С размером чанков можно играться.
Алгоритм вышел такой:
1. Создаем пул для кеширвоания подключения к БД
2. Определяем размер чанка(на основе ограничений ОЗУ)
3. Узнаем размер таблицы и вычисляем количество шагов
4. Делаем запрос чанка со сдвигом
5. Выводим пользователю результат
6. Если чанки не кончились идем в п 4
Из минусов, не лочится таблица, а значит не гарантии целостного результата, если данные были измененны между запросами. Если это не важно, то не парься. Если важно. то нужно придумать как лочить таблицу на запись на время выполнения скрипта,
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы