C# - 使用存储过程插入多行

时间:2010-05-19 14:09:30

标签: c# sql-server stored-procedures ado.net

我有一个对象列表,这个列表包含大约400万个对象。有一个存储过程,它将对象属性作为参数,进行一些查找并将它们插入表中。

将这400万个对象插入db的最有效方法是什么?

我是怎么做的:

-- connect to sql - SQLConnection ...

foreach(var item in listofobjects)
{    
   SQLCommand sc = ...

   // assign params

   sc.ExecuteQuery();    
}

这一直很慢。

有更好的方法吗?

这个过程将是一个预定的任务。我会用这个小时运行,所以我确实希望这样的高容量数据。

5 个答案:

答案 0 :(得分:8)

查看SqlBulkCopy Class

根据您的评论,将数据转储到临时表中,然后根据proc进行查找并插入真实表集......它将比逐行快得多

答案 1 :(得分:2)

从C#插入四百万条记录永远不会是理想的,但更好的方法是在代码中构建命令文本,这样你就可以在块中完成。

这几乎不是防弹的,它没有说明如何合并查找(正如你所提到的那样),但基本的想法是:

// You'd modify this to chunk it out - only testing can tell you the right
// number - perhaps 100 at a time.

for(int i=0; i < items.length; i++) {

    // e.g., 'insert dbo.Customer values(@firstName1, @lastName1)'
    string newStatement = string.Format(
        "insert dbo.Customer values(@firstName{0}, @lastName{0})", i);
    command.CommandText += newStatement;

    command.Parameters.Add("@firstName" + i, items[i].FirstName);
    command.Parameters.Add("@lastName" + i, items[i].LastName);
}
// ...
command.ExecuteNonQuery();

答案 2 :(得分:2)

我使用XML获得了很好的结果,可以将大量数据导入SQL Server。像你一样,我最初是一次插入一行,由于应用程序和服务器之间的往返时间,因此我将切换逻辑以传入包含要插入的所有行的XML字符串。插入时间从30分钟缩短到不到5秒。这是几千行。我已经测试了大小为20兆字节的XML字符串,没有任何问题。根据您的行大小,这可能是一个选项。

使用nText类型将数据作为XML String传入。

这样的事情构成了完成工作的存储过程的基本细节:

CREATE PROCEDURE XMLInsertPr(@XmlString ntext)  
DECLARE @ReturnStatus int,@ droc int

EXEC @ReturnStatus = sp_xml_preparedocument @hdoc OUTPUT,@ XmlString  
IF(@ReturnStatus&lt;&gt; 0)  
BEGIN  
RAISERROR('无法打开XML文档',16,1,50003)  
RETURN @ReturnStatus  
END  
 
INSERT INTO TableName  
SELECT * FROM OPENXML(@hdoc,'/ XMLData / Data')WITH TableName  
END

答案 3 :(得分:1)

您可以考虑删除正在插入的表上的任何索引,然后在插入所有内容后重新创建它们。我不确定批量复制类是如何工作的,但是如果你在每个插件上更新你的索引,它可能会减慢很多东西。

答案 4 :(得分:0)

  1. 像Abe一样提到:删除索引(并稍后重新创建)
  2. 如果您信任您的数据:为每次调用存储过程生成一个sql语句,组合一些,然后执行。
    这可以节省您的通信费用。
  3. 组合调用(到存储过程)可以包含在BEGIN TRANSACTION中,因此每x个插入只有一个提交
  4. 如果这是一次性操作:不进行优化并在夜间/周末运行