Страницы

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

четверг, 5 декабря 2019 г.

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

#c_sharp #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 секунды. Но вместе с этим появилась закономерная
проблема - чтобы изменить хоть что–то у пользователя, надо десериализовывать и сериализовывать
все его данные. 

Подскажите, какие существуют подходы сохранения больших объемов данных применимые
в данном случае не используя сериализацию? 
    


Ответы

Ответ 1



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

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

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