我正在使用带有Xamarin.Android的Microsoft.EntityFrameworkCore 2.0,我必须向SQLite数据库添加超过400000个项目,但我发现这样做的过程非常缓慢。例如,仅添加1024个项目需要3到4秒。
我遇到的问题是我不知道我做错了什么,或者有更好的方法来完成这项任务(任何优化建议都会受到欢迎)。这次是我们在这种情况下可以完成的最佳性能吗?
我的想法是按批次1024处理/插入400000个项目但是有了这个性能并做了一些保守的数学计算,处理所有项目需要20多分钟,而这次是不可接受的。我一直在努力尝试不同的批次,但表现并没有提高。
为了看看发生了什么,我创建了一些简单的基准代码,这是我的方法:
这是我正在使用的实体:
public sealed class BenchmarkEntityPoint
{
public BenchmarkEntityPoint()
{
}
public BenchmarkEntityPoint(long field1, double field2, double field3, double field4, double field5, double field6, double field7, double field8)
{
Field1 = field1;
Field2 = field2;
Field3 = field3;
Field4 = field4;
Field5 = field5;
Field6 = field6;
Field7 = field7;
Field8 = field8;
}
public int Id { get; set; }
public long Field1 { get; set; }
public double Field2 { get; internal set; }
public double Field3 { get; internal set; }
public double Field4 { get; internal set; }
public double Field5 { get; internal set; }
public double Field6 { get; internal set; }
public double Field7 { get; internal set; }
public double Field8 { get; internal set; }
}
这是我的DbContext:
public sealed class BenchmarkContext : DbContext
{
private readonly string path;
public BenchmarkContext(string path)
{
this.path = path;
ChangeTracker.AutoDetectChangesEnabled = false;
}
public DbSet<BenchmarkEntityPoint> BenchmarkEntityPoints { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<BenchmarkEntityPoint>().HasIndex(arg => arg.Field1);
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite($"Filename={path}");
}
}
...在某些活动中,我有以下测试方法
private void OnBenchmarkStart(object sender, System.EventArgs e)
{
var benchmarkPath = Path.Combine(global::Android.OS.Environment.ExternalStorageDirectory.AbsolutePath, "EFCBENCHMARKS", "benchmark1");
var context = // create the context
var points = // generate 1024 points to test
var mark = DateTimeOffset.Now;
context.BenchmarkEntityPoints.AddRange(points);
context.SaveChanges();
var elapsed = (DateTimeOffset.Now - mark).TotalMilliseconds;
// always getting between 3 and 4 sencods
}