[英]EntityFramework insert speed is very slow with large quantity of data
我試圖通過Entity Framework 6.1.3向MS Sql Server數據庫插入大約50.000行,但這需要太長時間。 我聽了這個回答 。 在添加每1000個實體后禁用AutoDetectChangesEnabled並調用SaveChanges。 它仍然需要大約7-8分鍾。 我嘗試使用遠程服務器和本地服務器。 沒有太大區別。 我不認為這是正常的。 我忘記了什么嗎?
這是我的代碼:
static void Main(string[] args)
{
var personCount = 50000;
var personList = new List<Person>();
var random = new Random();
for (int i = 0; i < personCount; i++)
{
personList.Add(new Person
{
CreateDate = DateTime.Now,
DateOfBirth = DateTime.Now,
FirstName = "Name",
IsActive = true,
IsDeleted = false,
LastName = "Surname",
PhoneNumber = "01234567890",
PlaceOfBirth = "Trabzon",
Value0 = random.NextDouble(),
Value1 = random.Next(),
Value10 = random.NextDouble(),
Value2 = random.Next(),
Value3 = random.Next(),
Value4 = random.Next(),
Value5 = random.Next(),
Value6 = "Value6",
Value7 = "Value7",
Value8 = "Value8",
Value9 = random.NextDouble()
});
}
MyDbContext context = null;
try
{
context = new MyDbContext();
context.Configuration.AutoDetectChangesEnabled = false;
int count = 0;
foreach (var entityToInsert in personList)
{
++count;
context = AddToContext(context, entityToInsert, count, 1000, true);
}
context.SaveChanges();
}
finally
{
if (context != null)
context.Dispose();
}
}
private static MyDbContext AddToContext(MyDbContext context, Person entity, int count, int commitCount, bool recreateContext)
{
context.Set<Person>().Add(entity);
if (count % commitCount == 0)
{
context.SaveChanges();
if (recreateContext)
{
context.Dispose();
context = new MyDbContext();
context.Configuration.AutoDetectChangesEnabled = false;
}
}
return context;
}
人員類:
public class Person
{
public int Id { get; set; }
[MaxLength(50)]
public string FirstName { get; set; }
[MaxLength(50)]
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
[MaxLength(50)]
public string PlaceOfBirth { get; set; }
[MaxLength(15)]
public string PhoneNumber { get; set; }
public bool IsActive { get; set; }
public DateTime CreateDate { get; set; }
public int Value1 { get; set; }
public int Value2 { get; set; }
public int Value3 { get; set; }
public int Value4 { get; set; }
public int Value5 { get; set; }
[MaxLength(50)]
public string Value6 { get; set; }
[MaxLength(50)]
public string Value7 { get; set; }
[MaxLength(50)]
public string Value8 { get; set; }
public double Value9 { get; set; }
public double Value10 { get; set; }
public double Value0 { get; set; }
public bool IsDeleted { get; set; }
}
從分析器跟蹤的查詢:
exec sp_executesql N'INSERT [dbo].[Person]([FirstName], [LastName], [DateOfBirth], [PlaceOfBirth], [PhoneNumber], [IsActive], [CreateDate], [Value1], [Value2], [Value3], [Value4], [Value5], [Value6], [Value7], [Value8], [Value9], [Value10], [Value0], [IsDeleted])
VALUES (@0, @1, @2, @3, @4, @5, @6, @7, @8, @9, @10, @11, @12, @13, @14, @15, @16, @17, @18)
SELECT [Id]
FROM [dbo].[Person]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()',N'@0 nvarchar(50),@1 nvarchar(50),@2 datetime2(7),@3 nvarchar(50),@4 nvarchar(15),@5 bit,@6 datetime2(7),@7 int,@8 int,@9 int,@10 int,@11 int,@12 nvarchar(50),@13 nvarchar(50),@14 nvarchar(50),@15 float,@16 float,@17 float,@18 bit',@0=N'Name',@1=N'Surname',@2='2017-01-19 10:59:09.9882591',@3=N'Trabzon',@4=N'01234567890',@5=1,@6='2017-01-19 10:59:09.9882591',@7=731825903,@8=1869842619,@9=1701414555,@10=1468342767,@11=1962019787,@12=N'Value6',@13=N'Value7',@14=N'Value8',@15=0,65330243467041405,@16=0,85324223938083377,@17=0,7146566792925152,@18=0
我想用EF解決這個問題。 我現在有很多選擇。 但我們假設沒有其他機會。
這里的主要問題是,我使用了與我引用的答案相同的方法。 它在191秒內插入560000個實體。 但我只能在7分鍾內插入50000。
您已經通過禁用AutoDetectChanges擺脫了ChangeTracker問題。
我通常建議使用以下解決方案之一:
請參閱: http : //entityframework.net/improve-ef-add-performance
由於您已將AutoDectectChanges設置為false,因此進行多個批次不會真正改善或降低性能。
主要問題是實體框架為您需要插入的每個實體進行數據庫往返。 因此,如果您插入50,000個實體,則執行50,000個數據庫往返,即INSANE 。
您需要做的就是減少數據庫往返次數。
一種免費的方法是使用SqlBulkCopy: https ://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy( v= vs.110).aspx
免責聲明 :我是Entity Framework Extensions的所有者
該庫允許您執行場景所需的所有批量操作:
您將能夠在幾秒鍾內插入50,000個實體。
例
// Easy to use
context.BulkSaveChanges();
// Easy to customize
context.BulkSaveChanges(bulk => bulk.BatchSize = 100);
// Perform Bulk Operations
context.BulkDelete(customers);
context.BulkInsert(customers);
context.BulkUpdate(customers);
// Customize Primary Key
context.BulkMerge(customers, operation => {
operation.ColumnPrimaryKeyExpression =
customer => customer.Code;
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.