繁体   English   中英

使用LINQ2SQL插入大量记录

[英]Using LINQ2SQL to insert a large number of records

我们有一个小的c#工具,我们将它们拼凑在一起来解析数据文件,构建一些对象并将它们插入到数据库中。

逻辑本质上是。

string [] lines = File.ReadAllLines("C:\\Temp\\Data.dat")

foreach(string line in lines)
{
    MyDataObject obj = ParseObject(line);
    myDataContext.MyDataObjects.InsertOnSubmit(obj);
}

myDataContext.SubmitChanges();

这在一开始就很好,因为数据文件每天只有大约1000行,但是最近这个文件已经增长到大约30,000行,并且这个过程变得非常缓慢。

SubmitChanges()调用的所有内容都可以,但是一旦它开始向数据库转储30,000个插入的过程,它就会停止运行。 作为一项测试,我发了30,000个插入语句并直接从QA运行。 花了大约8分钟。

8分钟后,C#/ Linq版本仅完成了大约25%的插入。

有人建议我如何优化这个吗?

如果您正在编写大量的同类数据, SqlBulkCopy可能是一个更合适的工具,例如可能使用CsvReader读取行(因为SqlBulkCopy可以接受IDataReader ,这意味着您不必将所有30k行缓冲到内存中) 。

如果数据是CSV,则可以这样简单:

using (CsvReader reader = new CsvReader(path))
using (SqlBulkCopy bcp = new SqlBulkCopy(CONNECTION_STRING))
{
    bcp.DestinationTableName = "SomeTable";
    bcp.WriteToServer(reader);
}

如果数据更复杂(不是CSV),则SimpleDataReader可能很有用 - 您只需将其子类化并添加代码以表示每行的数据。

我前段时间有同样的问题。 我在数据库中插入1000000个新条目,我发现每500个调用SubmitChanges是最快的方法。

我不能保证当时500排是最快的,我们的环境很奇怪......

您可能想尝试多线程方法。

  1. 将记录集分区为较小的大小(每个1000个?),将它们放入堆栈
  2. 有一个类将从堆栈顶部获取记录集并开始使用多线程类插入它,该类打开DataContext并自行插入。
  3. 在插入时,会为下一组记录打开第二个类
  4. 内部逻辑决定一次可以运行多少个插件(5?10?)

这可能允许插入比仅仅每隔几条记录运行SubmitChanges()更快地进行,因为多个插入可以同时发生。

这是一个数据库任务,应该通过SSIS并使用批量插入来完成。

我可以在几秒或几毫秒内插入30,000条记录(取决于列数和数据映射的复杂程度)。 我拥有超过一百万条记录的导入,这些记录的插入时间比您每次循环读取一条记录的时间短。 我甚至有一个2000万的记录文件,只需要16分钟。

老问题,但在寻找我自己的解决方案之后,我遇到了这个代码项目文章非常好。 基本上使用Linq2Sql属性来构建DataTable,然后使用SQLBulkCopy进行插入,这比基本的Linq2Sql实现要快得多。 文章中的代码可能会使用一些清理,并且可能会在使用外键的更复杂场景中出现(我的模型中没有任何内容,尽管在数据库中有)但完全符合我的需求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM