Есть у меня мелкая утилитка, которая сохраняет данные в csv. Данных стало слишком много, и искать по ним все сложнее. Поэтому я решил сконвертировать csv в что-то более удобное. Решил попробовать самый простой вариант с точки зрения трудозатрат — EF на SQLite.
Быстро написал небольшой алгоритм читающий из csv и пишущий в 3 таблички в SQLite. Запустил, процесс пошел. Но как-то небыстро. Сходил попить чай, и вернувшись обнаружил что скорость упала где-то до 1 записи в секунду. O_o А всего записей несколько миллионов. Поэтому пришлось думать над оптимизацией, а на нее время тратить не хотелось.
Первым делом добавил локальный кэш, где это было возможно благодаря особенностям данных. Это увеличило скорость раза в 2-3. Но это ситуацию никак не спасало. Чуть переделал алгоритм, чтобы по минимум использовать объекты EF. То есть по возможности запрашивать примитивные типы (long), вместо всего объекта. Это дало небольшой результат, но кардинально ничего не меняло. Пришлось думать дальше.
Записи писались по одной. То есть одна запись — одна транзакция. Просто для 2-х из 3-х таблиц нужно было проверять, а нет ли этой записи уже в таблице, так как в csv информация дублировалась. А если транзакцию не закомитить, новая запись не ищется. Поэтому я решил переделать алгоритм на добавление пачками.
Но с SQLite оказалось не все так просто. Для этого пришлось бы кэшировать только что созданные объекты, чтобы в последующих записях использовать их id при добавления в базу. Кэш таких объектов я довольно быстро написал (они ведь в базе до коммита не ищутся), но обнаружил одну неприятную особенность. После добавления новой записи в возвращаемом объекте id нулевой. Причем внутри структуры есть internal объект, в котором "новый" id есть, а наружу он не отдается. А без этого id невозможно добавлять последующие записи. А комитить транзакцию на каждой новой записи... это не сильно будет отличатся от изначального варианта.
Попытался нагуглить что-нибудь похожее. Нашел на stack overflow похожую проблему, но без каких-либо вариантов решения (по крайней мере тех, что я ещё не пробовал). В итоге плюнул, и переписал все на SQL запросы "мимо" EF. В итоге скорость выросла в 28 раз. Вот такие вот сюрпризы подкидывает EF.