2013-09-05 3 views
1

У меня есть полностью работающий производственный сайт на основе сущности framework, и теперь мне нужно импортировать большое количество данных еженедельно в базу данных. данные поступают в виде текстовых файлов, которые я просматриваю по строкам, проверяю базу данных, чтобы узнать, существует ли она и обновляет ли что-либо, что изменилось, или просто вставить его, если нет. проблема, связанная с тем, что для полного процесса импорта требуется около 32 часов, а некоторые из них должны быть разделены на меньшие части, чтобы избежать проблем с памятью, которые, по-видимому, вызваны инфраструктурой сущности. мне удалось замедлить увеличение памяти, но в последний раз, когда я запускал файл, не разбивая его, он работал около 12 часов, прежде чем закончилась нехватка памяти в 1,5 ГБ. , так что кто-то может предложить мне лучший способ импорта этих данных, я слышал о sqlbulkcopy, но не был уверен, что это была правильная вещь для использования. может ли кто-нибудь представить какие-либо примеры? или предложить что-нибудь более подходящее. например, должен ли я создать дубликат объекта с использованием стандартных команд .net sql и, возможно, использовать хранимую процедуруобход Entity Framework для импорта/обновления большого количества данных

+0

Я предлагаю вам использовать BCP для импорта данных, а затем использовать raw SQL для объединения/обновления данных. Это не то, что вам следует делать с EF. – qujck

+0

Итак, по строкам вы разбираете текстовый файл.Затем вы используете EF по очереди для обновления или вставки? Bulkcopy только вставляет, поэтому вам нужно больше узнать об этом процессе. Может быть пакет для вставки для крупноформатной копии, но тогда потенциальная проблема - это запись, которая не знает, что это обновление, если эта запись находится в пакете вставки, еще не обработанном. – Paparazzi

+2

Сколько строк? Как долго? –

ответ

2

Хотя SqlBulkCopy удобно из управляемого кода, я думаю, самый быстрый способ сделать это в «чистом» SQL - учитывая, что SqlBulkCopy не легко сделать upserts, вы должны выполнить MERGE часть ниже в любом случае

Предполагая, что ваш текстовый файл находится в формате csv, и он существует на SQL Server как «C: \ Data \ TheFile.txt», и это окончание строк нормируется как CR-LF (\ r \ n)

И давайте предположим, что данные ID, Value1, Value2

Эта команда SQL будет вставляться в промежуточную таблицу TheFile_Staging, которая имеет столбцы ID, Value, Value2 с совместимыми типами данных, а затем обновить «реальную» таблицу TheFile_Table (примечание: код ниже не проверяли!)

truncate table TheFile_Staging 
    BULK INSERT TheFile_Staging FROM'C:\Data\TheFile.txt' 
WITH (fieldterminator=',', rowTerminator='\r\n',FirstRow=2) 
    //FirstRow=2 means skip Row#1 - use this when 1st row is a header. 

MERGE TheFile_Table as target 
USING (SELECT ID,Value1,Value2 from TheFile_Staging) as source 
on target.ID = source.ID 
WHEN MATCHED THEN 
    UPDATE SET target.Value1=source.Value1, target.Value2=source.target2 
WHEN NOT MATCHED THEN 
    INSERT (id,Value1,Value2) VALUES (source.Id,source.Value1,source.Value2); 

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

Обычно я добавляю какую-либо проверку валидации в предложение WHERE, чтобы мы использовали USER() select MERGE, чтобы принимать только строки, которые являются действительными в терминах данных.

Возможно, также стоит отметить, что определение промежуточной таблицы должно опускать любые ненулевые, первичные ключи и ограничения идентификации, чтобы данные могли считываться без ошибок esp. если в исходных данных есть пустые поля; и я также обычно предпочитаю использовать данные даты/времени как обычный nvarchar - таким образом вы избегаете неправильных отформатированных дат, вызывающих ошибки импорта, и ваш оператор MERGE может выполнять CAST или CONVERT по мере необходимости, в то же время игнорируя и/или регистрируя в таблице ошибок имеются недопустимые данные.

+0

Я пробовал это, но не смог заставить его работать с моим файлом. вот пример ... "customer_id" \t "CustomerName" \t "CustomerAddress" \t "CustomerGender" \t "CustomerBirthDate" "Джордан Reyes Toribio" \t "100 тест адрес" \t "FE" \t 1962-02 -09 00:00:00 –

+0

@TomHawkin, извините, что он не работает для вас; можете ли вы дать некоторые сведения об этой ошибке, которую вы получите, когда попробуете? –

+0

В настоящее время ошибкой является «Ошибка преобразования данных массовой загрузки (несоответствие типа или недопустимый символ для указанной кодовой страницы) для строки 1, столбец 4 (CustomerGender)». Поле является nvarchar (10) –

0

К сожалению, вам нужно уйти от Entity Framework в таком сценарии; из коробки EF выполняет только линейные вставки. Вы можете делать интересные вещи, такие как this, или вы можете полностью игнорировать EF и вручную кодировать класс, который будет делать объемные вставки с помощью ADO.Net (SqlBulkCopy).

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

Смежные вопросы