Вставка большого количества строк в SQL CE 4.0 с Entity Framework 4 (проблема производительности) - PullRequest
8 голосов
/ 11 августа 2011

У меня есть небольшая база данных SQL CE 4.0 с несколькими таблицами, сопоставленными с помощью Entity Framework 4.

Вот код, который у меня есть

foreach (String designation in newItemDesignations)
{
    ParameterData defaultValue = PDM.GetDefaultParameterData(designation);

    // Fill the ItemParameterDBO object with the data
    ItemParameterDBO dbParam = new ItemParameterDBO();
    dbParam.ItemID = dbItem.ID;
    dbParam.Designation = designation;    
    dbParam.High = defaultValue.High;
    dbParam.Low = defaultValue.Low;

    database.ItemParameterDBOes.AddObject(dbParam);
}

database.SaveChanges();

Этот код появляется 24 times, и каждый раз, когда список newItemDesignations содержит exactly 525 elements. Это всего 12600 строк для добавления.

Полный процесс длится 509 seconds. Я думаю, это слишком много для 12600 строк.

Мне известно, что я звоню SaveChanges 24 times. На данный момент дизайн приложения не позволяет мне поместить все вставки в одну транзакцию (с SaveChanges). Однако посмотрите, что происходит с одной транзакцией. 509 / 24 = 21 seconds, или 40 ms per row.

  • Является ли 40 мс нормальным (средним) временем для вставки строки через EF4?

Я проверил мой другой код (кроме добавления в базу данных и сохранения изменений). Для всех 12600 строк требуется всего 100 мс. Это 0,01% полного времени, так что это, очевидно, не проблема. 99,99% времени обработки тратится в EF4 AddObject и SaveChanges.

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

Также обратите внимание: ни в одной из таблиц не заданы индексы (кроме первичных / внешних ключей)

  • Что я здесь не так делаю, почему это так медленно?
  • Это нормальное время, необходимое для вставки такого количества строк, или это какие-то ограничения производительности, связанные с SQL CE 4?

Ответы [ 3 ]

10 голосов
/ 12 августа 2011

Поскольку примеров мало, вот код, который я тестировал, и он работал безупречно.Благодаря ErikEJ's SqlCeBulkCopy библиотеке.Должно быть.

DataTable table = new DataTable();

table.Columns.Add(new DataColumn("A", typeof(int)));
table.Columns.Add(new DataColumn("B", typeof(String)));
table.Columns.Add(new DataColumn("C", typeof(Byte)));

for(int i = 0; i < 12000; i++)
{
    DataRow row = table.NewRow();
    row["A"] = "124324"
    row["B"] = "something";
    row["C"] = 15;

    table.Rows.Add(row);
}

String connString = @"Data Source = C:\Database.sdf";
SqlCeBulkCopy bulkInsert = new SqlCeBulkCopy(connString);
bulkInsert.DestinationTableName = "Items";
bulkInsert.WriteToServer(table);

Вставка моих (OP) 12600 строк заняла менее 2 секунд.

Этот пример плохой, он не является строго типизированным, но он описывает, как вручную создать таблицу данных и вставить ее в базу данных с помощью библиотеки SqlCeBulkCopy (см. принятый ответ для ссылки).

6 голосов
/ 11 августа 2011

Вы можете использовать мою библиотеку SqlCeBulkCopy, чтобы обойти EF http://sqlcebulkcopy.codeplex.com

1 голос
/ 12 августа 2011

Для дальнейшего ответа ErikEJ и вашего собственного примера вы можете использовать реализацию IDataReader над списками для потоковой передачи данных в WriteToServer вместо дублирования значений через DataTable.См. Этот вопрос:

Получить IDataReader из типизированного списка

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

...