#javascript #node.js #mongodb
Вопрос:
Вариант использования заключается в том, что пользователь может экспортировать любое количество данных из базы данных в Excel. Структура данных динамична и определяется пользователем с помощью какого-либо конструктора форм, что означает, что теоретически в каждых данных может быть любое количество полей [1, n].
В коллекции данных структура [field_id]: [значение поля]. field_id-это идентификатор объекта, приведенный в строку, ссылающийся на другую коллекцию, называемую формой, в которой хранится многочисленная информация об этом поле (например, тип данных, такой как текст/дата/число, определяющий, как следует анализировать значение).значение field_value может быть любым типом данных, таким как массив, строка, объект, целое число или даже внешний ключ(коллекция, к которой нужно присоединиться, снова хранится в коллекции форм). Примером поля может быть :
"6046e684f8fcf17b7c79c65e": [ObjectId("6045ed759282db8b7db270c3")],
Причина, по которой я решил использовать внешний ключ вместо денормализации, заключается в том, что нет смысла обновлять неизвестное количество данных при изменении ссылочного значения. Например, если в пользователе имеется 100 000 данных, ссылающихся на документ, мне придется обновлять 100 000 документов каждый раз, когда указанный пользовательский документ изменяется.
Очевидно, что производительность становится очень низкой по мере увеличения размера набора данных и еще хуже, если в поле хранится внешний ключ (так как мне нужно отправить еще один запрос в базу данных для поиска отображаемого значения).
Вот как я анализировал данные :
- Разделите процесс экспорта на части, чтобы каждый раз я анализировал только определенное количество строк за один раз(вместо того, чтобы запрашивать 100 000 строк одновременно).
- Для полей, которые ссылаются на другие коллекции, я сохраняю результат запроса в массив, чтобы будущая обработка того же идентификатора объекта в field_value могла получить значение непосредственно из памяти вместо повторного запроса в БД. Что-то вроде:
const search = []
...
//during processing
const find = search.find(item => item.id === data[i][field_value]) //data[i][field_value] is an id
if (!find) {
const result = await Collection.findById(data[i][field_value]).lean();
search.push(result)
}
...
Меня беспокоят 2 вещи в целом: 1) сервер перегружен, когда многие пользователи одновременно экспортируют очень большие данные, и 2) пользователю, возможно, придется очень долго ждать экспорта. Есть ли какие-либо другие способы улучшить производительность?
Комментарии:
1. Я могу предложить два предложения: (1) используйте ручной курсор для клиента MognoDB и запустите функцию чтения в циклах тиков процессов, когда вы получаете, скажем, 100 документов. (2) как только у вас появятся данные, добавьте их в файл CSV или XLSX вместо того, чтобы хранить их в памяти. (1) гарантирует, что вы не заблокируете цикл событий в течение длительного времени, и (2) гарантирует, что вы не будете тратить системную память во время обработки. Повторные добавления, возможно, немного медленнее, но, на мой взгляд, сокращение объема памяти в этом случае является гораздо большим преимуществом.