2015-02-18 1 views
0

У меня есть приложение MVC5, я использую службу базы данных EF6 и MySQL от Azure, которая является CleanDB MySQL. У меня есть класс чтения CSV, который работает довольно быстро в моем консольном приложении. Тогда, в мое приложение MVC, у меня есть модель, как это:Как повысить производительность записи в базу данных в MVC5?

Provider.cs

public class Provider 
{ 
    public int ProviderId { get; set; } 

    public string ProviderName { get; set; } 

    public string Email { get; set; } 

    public string Address { get; set; } 

    public string City { get; set; } 

    [ForeignKey("State")] 
    public int StateID { get; set; } 

    public virtual State State { get; set; } 

    public string Zip { get; set; } 

    public string Phone { get; set; } 

    public string Fax { get; set; } 

    public string SICCode { get; set; } 

    public string Description { get; set; } 

    public string Website { get; set; } 

    public string RefId { get; set; } 
} 

Тогда, на мой Configuration.cs файл, у меня есть что-то вроде этого:

string[] csvs = Directory.GetFiles(@"C:\Users\User\Downloads\db\test\"); 

foreach (string csv in csvs) 
{ 
    using (CsvReader reader = new CsvReader(csv)) 
    { 
     foreach (string[] values in reader.RowEnumerator) 
     { 
      var provider = new Provider(); 
      provider.ProviderName = values[0]; 
      provider.Email = values[1]; 
      provider.Address = values[2]; 
      provider.City = values[3]; 
      provider.StateID = 491; 
      provider.Zip = values[5]; 
      provider.Phone = values[6]; 
      provider.Fax = values[7]; 
      provider.SICCode = values[8]; 
      provider.Description = values[9]; 
      provider.Website = values[10]; 
      provider.RefId = ""; 

      context.Providers.Add(provider); 
     } 
    } 
} 

context.SaveChanges(); 

Дело в том, что у меня есть около 50 файлов CSV, общий размер которых составляет 400 МБ, а всего около 9 миллионов. Только для целей тестирования я использовал самый маленький CSV-файл в моем списке, который был файлом размером 2 Мбайт, объемом около 15 тыс. Записей. Выполнение Update-Database заняло около 40 минут, чтобы поместить все эти записи в базу данных. Вы можете предположить, сколько времени мне понадобится для 9 миллионов записей. Любая идея ускорить процесс?

+1

Вы должны попробовать другой подход. Вероятно, EF не лучший инструмент для массовой загрузки данных. [Посмотрите здесь] (http://stackoverflow.com/questions/2821725/is-that-possible-to-do-bulk-copy-in-mysql) и [здесь] (http://stackoverflow.com/questions/ 4883376/how-to-bulk-insert-in-mysql-using-c-sharp) – Steve

+0

Где ваши приборы показывают время, затрачиваемое? IE, я предполагаю, что ваше решение для регистрации имеет временные метки, поэтому на основе этих временных меток наиболее дорогостоящие операции, которые вы выполняете? Когда дело касается вопросов производительности, измерьте меру измерения! –

+0

Стив прав. EF не предназначен для массовых операций (массовый импорт/экспорт). У каждой БД есть своя особенность. MSSQL, например, использует BCP. –

ответ

0

Вы уверены, что это действительно ваша производительность базы данных, в чем проблема? Не вызывая SaveChanges до конца, Entity Framework выполняет все операции в одной транзакции, поэтому, помимо времени транспортировки, вы просто имеете стандартную стоимость простого добавления 9 миллионов записей в любую таблицу базы данных. Не так много, что вы можете сделать по этому поводу, помимо предоставления дополнительных ресурсов вашему серверу базы данных, что может иметь или не иметь никакого влияния в зависимости от того, как ограничено ресурсами в настоящее время. Даже в самых худших сценариях время вашего транспорта для фактического запроса не должно превышать секунды, если только у вас нет худшего соединения в мире или вы пытаетесь сделать это через dialup или что-то еще.

Вероятно, ваш самый большой удар по производительности - это фактически поражение файловой системы и чтение из файлов CSV. Я бы посмотрел на ваш CSVReader и посмотрел, можно ли найти более эффективную замену. Кроме того, я не уверен, как работает эта библиотека, но если она передает файл из файловой системы, вероятно, было бы лучше просто сразу прочитать все это в памяти (если у вас достаточно ОЗУ). Доступ ко многим небольшим кластерам на диске обычно медленнее, чем чтение одного большого кластера. Очень грубая аналогия может заключаться в копировании файлов на USB-накопитель (так как это почти все мы имеем опыт). Я уверен, что вы заметили, что для копирования 4000 файлов 1 КБ требуется гораздо больше времени, чем для копирования одного файла размером 4 МБ, и только оттуда.

+0

Я попытался создать консольное приложение, где у меня был «Список all = new List ();' и поместил все значения столбцов всех строк из моего самого маленького файла CSV ('all.Add (значения [i]); '), и он закончил примерно через 1 секунду, используя мой CSV-ридер, и когда я сделал что-то вроде' all.Count', в списке было около 160 тыс. записей, что, я думаю, верно. Похоже, что мой читатель CSV хорошо читает. – tett

+0

Не читать из памяти. Все будет хорошо работать. Я говорю о чтении из файловой системы. –

+0

Я имел в виду, что мой код был точно таким же, как приведенный выше код, где я читал из CSV-файла на своем компьютере, за исключением того, что вместо создания нового поставщика и назначения ему значений я создал один «Список » и присвоил значения там , Любой код, который может мне помочь? Я не могу делать 'MySqlBulkLoad', пока я знаю, что CleanDB MySQL не позволяет подобные вещи из-за проблем с безопасностью. – tett

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