使用Linq到Sql的插入过程非常慢

JPR*_*ddy 9 c# sql-server linq-to-sql

我正在使用LinqToSql从C#向SqlServer 2008 Express DB插入大量记录.看起来插入速度非常慢.以下是代码段.

public void InsertData(int id)
{

  MyDataContext dc = new MyDataContext();

  List<Item> result = GetItems(id);

  foreach (var item in result)
  {
    DbItem dbItem = new DbItem(){ItemNo = item.No, ItemName=item.Name};
    dc.Items.InsertOnSubmit();
  }

  dc.SubmitChanges();
}
Run Code Online (Sandbox Code Playgroud)

我做错了吗?或者使用Linq插入大量记录是一个糟糕的选择?

更新:感谢您的所有答案. @ p.campbell:对于记录计数很抱歉,这是一个错字,实际上是100000左右.记录也一直到200k.

根据所有建议,我将此操作移动到部分(也是需求更改和设计决策),并以小块的形式检索数据,并在它到来时将它们插入到数据库中.我已将此InsertData()方法放在线程操作中,现在使用SmartThreadPool创建一个包含25个线程的池来执行相同的操作.在这种情况下,我一次只插入100条记录.现在,当我尝试使用Linq或SQL查询时,它在时间方面没有任何区别.

根据我的要求,此操作计划每小时运行一次,并为大约4k-6k用户提取记录.所以,现在我将每个用户数据(检索和插入到数据库)操作汇集为一个任务并分配给一个线程.现在整个过程大约需要45分钟,大约有250,000条记录.

有没有更好的方法来完成这种任务?或者任何人都可以建议我如何改进这个过程?

bad*_*d99 12

用于在oner中将大量数据插入SQL中

Linq或SqlCommand,都不是为将数据批量复制到SQL而设计的.

您可以使用SqlBulkCopy类,它提供对bcp实用程序的托管访问,以便从几乎任何数据源批量加载数据到Sql.

SqlBulkCopy类可用于仅将数据写入SQL Server表.但是,数据源不仅限于SQL Server; 只要数据可以加载到DataTable实例或使用IDataReader实例读取,就可以使用任何数据源.

性能比较

即使从简单的CSV文件加载数据,SqlBulkCopy也是最快的.

Linq将Insert在SQL中生成一堆语句并将它们发送到SQL Server.这与您使用Ad-hoc查询没有什么不同SqlCommand.SqlCommand与Linq的性能几乎完全相同.

证据

(SQL Express 2008,.Net 4.0)

SqlBulkCopy的

使用SqlBulkCopy从CSV文件加载100000行(包括加载数据)

using (SqlConnection conn = new SqlConnection("Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=EffectCatalogue;Data Source=.\\SQLEXPRESS;"))
{
    conn.Open();
    Stopwatch watch = Stopwatch.StartNew();

    string csvConnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\data\\;Extended Properties='text;'";
    OleDbDataAdapter oleda = new OleDbDataAdapter("SELECT * FROM [test.csv]", csvConnString);
    DataTable dt = new DataTable();
    oleda.Fill(dt);

    using (SqlBulkCopy copy = new SqlBulkCopy(conn))
    {
        copy.ColumnMappings.Add(0, 1);
        copy.ColumnMappings.Add(1, 2);
        copy.DestinationTableName = "dbo.Users";
        copy.WriteToServer(dt);
    }
    Console.WriteLine("SqlBulkCopy: {0}", watch.Elapsed);
}
Run Code Online (Sandbox Code Playgroud)

的SqlCommand

using (SqlConnection conn = new SqlConnection("Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=TestDb;Data Source=.\\SQLEXPRESS;"))
{
    conn.Open();
    Stopwatch watch = Stopwatch.StartNew();
    SqlCommand comm = new SqlCommand("INSERT INTO Users (UserName, [Password]) VALUES ('Simon', 'Password')", conn);
    for (int i = 0; i < 100000; i++)
    {
        comm.ExecuteNonQuery();
    }
    Console.WriteLine("SqlCommand: {0}", watch.Elapsed);
}
Run Code Online (Sandbox Code Playgroud)

LinqToSql

using (SqlConnection conn = new SqlConnection("Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=TestDb;Data Source=.\\SQLEXPRESS;"))
{
    conn.Open();
    Stopwatch watch = Stopwatch.StartNew();
    EffectCatalogueDataContext db = new EffectCatalogueDataContext(conn);
    for (int i = 0; i < 100000; i++)
    {
        User u = new User();
        u.UserName = "Simon";
        u.Password = "Password";
        db.Users.InsertOnSubmit(u);
    }
    db.SubmitChanges();
    Console.WriteLine("Linq: {0}", watch.Elapsed);
}
Run Code Online (Sandbox Code Playgroud)

结果

SqlBulkCopy: 00:00:02.90704339
SqlCommand: 00:00:50.4230604
Linq: 00:00:48.7702995
Run Code Online (Sandbox Code Playgroud)