Как ускорить процесс файла CSV? (5 миллионов и более записей)

Я написал консольную программу VB.net для обработки CSV-записи, поступающей в текстовый файл. Я использую библиотеку FileHelpers

вместе с библиотекой MSFT Enterprise 4. Читать записи по одной и вставлять в базу данных.

На обработку 5+ миллионов записей в текстовом файле ушло около 3-4 часов.

Можно ли как-то ускорить процесс? Кто-нибудь имел дело с таким большим количеством записей раньше, и как бы вы обновили такие записи, если есть новые данные для обновления?

edit: Может ли кто-нибудь порекомендовать профилировщик? предпочитаете с открытым исходным кодом или бесплатно.


person Jack    schedule 31.03.2009    source источник
comment
Почему бы просто не вставить эти данные непосредственно в базу данных SQL Server с помощью Microsoft SQL Server Management Studio?   -  person Konstantin Tarkus    schedule 01.04.2009
comment
Если его необходимо изменить, вы можете вставить его во временную таблицу, а затем применить свои изменения с помощью T-SQL.   -  person Konstantin Tarkus    schedule 01.04.2009
comment
Как вы делаете это автоматически? Без человеческого взаимодействия?   -  person Jack    schedule 01.04.2009


Ответы (12)


читать запись по одной и вставлять в базу данных

Прочитайте их партиями и вставьте их партиями.

person yfeldblum    schedule 31.03.2009
comment
Массовая вставка — ваш друг. msdn.microsoft.com/en-us/library/ms188365.aspx - person Joel Coehoorn; 01.04.2009

Воспользуйтесь профилировщиком — узнайте, куда уходит время.

Если не считать настоящего профилировщика, попробуйте следующее:

  • Время, сколько времени требуется, чтобы просто прочитать файлы построчно, ничего с ними не делая
  • Возьмите образец строки и засеките, сколько времени потребуется, чтобы просто разобрать ее и выполнить любую необходимую обработку, 5+ миллионов раз.
  • Генерировать случайные данные и вставлять их в базу данных, и время,

Я предполагаю, что база данных будет узким местом. Вам следует подумать о пакетной вставке - если вы вставляете только одну запись за раз, это, вероятно, будет намного медленнее, чем пакетная вставка.

person Jon Skeet    schedule 31.03.2009

Я делал много таких приложений в прошлом, и есть несколько способов оптимизации.

  1. Убедитесь, что код, который вы пишете, правильно управляет памятью, с чем-то вроде этого одна небольшая ошибка может замедлить процесс до сканирования.

  2. Подумайте о написании вызовов базы данных как асинхронных, так как это может быть узким местом, поэтому небольшая очередь может быть в порядке.

  3. Рассмотрите возможность удаления индексов, выполнения импорта, а затем повторного импорта.

  4. Рассмотрите возможность использования SSIS для импорта, он уже оптимизирован и делает такие вещи из коробки.

person Mitchel Sellers    schedule 31.03.2009
comment
Просто не тратьте на это слишком много времени — если это не что-то действительно очевидное (например, чтение файла по одному символу за раз, алгоритм экспоненциального времени или что-то столь же очевидное), вы тратите свое время впустую, когда пытаетесь спекулировать. где замедление. - person David Wolever; 01.04.2009
comment
@david Хороший момент, другое дело, что для моего пункта № 1 что-то вроде Ants Profiler может стать хорошим инструментом для устранения неполадок. - person Mitchel Sellers; 01.04.2009

Почему бы просто не вставить эти данные непосредственно в базу данных SQL Server с помощью Microsoft SQL Server Management Studio или командной строки — SQLCMD? Он знает, как обрабатывать файлы CVC.

Для свойства BulkInsert в вашей базе данных должно быть установлено значение True.

Если его необходимо изменить, вы можете вставить его во временную таблицу, а затем применить свои изменения с помощью T-SQL.

person Konstantin Tarkus    schedule 31.03.2009

Лучше всего было бы попробовать использовать профилировщик с относительно небольшой выборкой — это могло бы определить, где находятся фактические задержки.

person Rowland Shaw    schedule 31.03.2009

Загрузите его в память, а затем вставьте в БД. 5 миллионов строк не должны напрягать вашу память. Проблема в том, что вы, по сути, перегружаете свой диск - как читаете CSV, так и записываете в БД.

person Jeff    schedule 31.03.2009

Я бы ускорил его так же, как ускорил бы что угодно: запустив его через профилировщик и выяснив, что занимает больше всего времени.

Совершенно невозможно угадать, в чем здесь узкое место — может быть, в коде, который анализирует файл CSV, есть ошибка, что приводит к полиномиальному времени выполнения? Может быть, для обработки каждой строки используется какая-то очень сложная логика? Кто знает!

Кроме того, для «рекорда» 5 миллионов строк не НАСТОЛЬКО тяжелы — мне пришла в голову догадка, что разумная программа должна быть в состоянии обработать это за полчаса, а хорошая программа гораздо меньше.

Наконец, если вы обнаружите, что база данных является вашим узким местом, проверьте, фиксируется ли транзакция после каждой вставки. Это может привести к некоторому нетривиальному замедлению...

person David Wolever    schedule 31.03.2009
comment
@David, не недооценивайте 5 миллионов поездок туда и обратно, это может быть много в зависимости от среды. - person eglasius; 01.04.2009

Не уверен, что ты с ними делаешь, но думал ли ты о perl? Недавно я переписал vb-скрипт, который делал что-то похожее — обрабатывал тысячи записей — и время увеличилось с часа для vb-скрипта до 15 секунд для perl.

person chris    schedule 31.03.2009

После чтения всех записей из файла (я бы прочитал весь файл за один проход или по блокам), затем используйте класс SqlBulkCopy для импорта ваших записей в БД. Насколько я знаю, SqlBulkCopy — это быстрый подход к импорту блока записей. В Интернете есть несколько учебных пособий.

person Kyle B.    schedule 31.03.2009

Как предлагали другие, сначала профилируйте приложение.

Тем не менее, вы, вероятно, выиграете от пакетных вставок. Так было с одним приложением, с которым я работал, и оно оказало большое влияние.

Учтите, что 5 миллионов циклов — это много, особенно если каждый из них предназначен для простой вставки.

person eglasius    schedule 31.03.2009

В аналогичной ситуации мы увидели значительное улучшение производительности при переходе от вставки по одной строке за раз к использованию SqlBulkCopy API.

Есть хорошая статья здесь.

person Jason DeFontes    schedule 31.03.2009

Вам необходимо выполнить массовую загрузку данных в базу данных, если у нее есть такая возможность. В Sql Server вы будете смотреть на BCP, DTS или SSIS — BCP является самым старым, но, возможно, самым быстрым. OTOH, если это невозможно в вашей БД, отключите все индексы перед запуском, я предполагаю, что проблемы вызывает БД, а не код .Net.

person MrTelly    schedule 31.03.2009