Страницы

Поиск по вопросам

четверг, 11 октября 2018 г.

Сохранение больших объемов данных в базу данных используя entity framework

Программа парсит через VK API пользователей (в среднем в 20-50 потоков) и создает записи в базе данных. У каждого пользователя в среднем 20 групп, 500 фотографий, 200 друзей. Я храню в разных таблицах записи о друзьях, группах, пользователях и фотографиях. Итого, чтобы сохранить 1го пользователя у меня уходит около 721 запросов на вставку в базу. В минуту это 200-300 пользователей- ~216 000 запросов на вставку в базу. Из за этого вызов context.SaveChanges() отнимает около 6-10 минут на выполнение.
Пробовал использовать пул контекстов - bulk insert, среднее время- 4-6 минут.
AutoDetectChangesEnabled = false; или context.AddRange() дают примерно те же результаты.
Единственное быстрое решение, к которому я пришел - бинарно сериализовывать данные пользователя и хранить их в byte[], чтобы на юзера было 4 запроса вставки. Это сократило время вызова context.SaveChanges() до 1.2 секунды. Но вместе с этим появилась закономерная проблема - чтобы изменить хоть что–то у пользователя, надо десериализовывать и сериализовывать все его данные.
Подскажите, какие существуют подходы сохранения больших объемов данных применимые в данном случае не используя сериализацию?


Ответ

Не нужно вызывать context.SaveChanges() на каждый чих.
Вставить 1000 записей за 1 context.SaveChanges() быстрее, чем на каждую запись вызвать context.SaveChanges(). Если у тебя присутсвует какая-то сложная логика, то лучше эту логику вынести в хранимую процедуру. Если БД и приложение находится на разных машинах, то возможно стоит проверить скорость сети. Огромное кол-во индексов может тормозить встаку. Отказаться вообще от EF прии вставках и рулить этим делом через BulkCopy.
Например, заливаешь все массово в какую-нибудь таблицу на сервере, затем JOB каждые 5 минут опрашивает эту таблицу и выполняет добавление информации по рабочим таблицам. Еще бы профайлером не помешало бы посмотреть запросы, который формирует EF.
Может быть они не оптимальны и стоит пошаманить с LINQ.
Я бы посоветовал замерить заполнение БД через BulkCopy(Самый быстрый способ множественных вставок) и тогда ты получишь величину к которой ты должен стримиться и выше которой не прыгнешь, используя EF.

Комментариев нет:

Отправить комментарий