Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C-使用存储过程插入多行_C#_Sql Server_Stored Procedures_Ado.net - Fatal编程技术网

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

C# C-使用存储过程插入多行,c#,sql-server,stored-procedures,ado.net,C#,Sql Server,Stored Procedures,Ado.net,我有一个对象列表,这个列表包含大约400万个对象。有一个存储过程,它将对象属性作为参数,进行一些查找并将它们插入表中 将这400万个对象插入数据库最有效的方法是什么 我怎么做: -- connect to sql - SQLConnection ... foreach(var item in listofobjects) { SQLCommand sc = ... // assign params sc.ExecuteQuery(); } 这真的很慢 有

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

将这400万个对象插入数据库最有效的方法是什么

我怎么做:

-- connect to sql - SQLConnection ...

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

   // assign params

   sc.ExecuteQuery();    
}
这真的很慢

有更好的方法吗

此过程将是一个计划任务。我将在每小时运行一次,因此我确实希望获得像这样的高容量数据。

请查看


根据您的评论,将数据转储到一个暂存表中,然后执行查找并插入到基于进程的实际表集中……这将比逐行插入的速度快得多。从C插入400万条记录从来都不是理想的做法,但更好的方法是在代码中构建命令文本,这样您就可以分块执行

这很难说是防弹的,它没有说明如何按照您所提到的需要合并查找,但其基本思想是:

// 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();

你可以考虑在你插入的表中删除任何索引,然后在插入所有东西之后再创建它们。我不确定bulk copy类是如何工作的,但是如果您在每次插入时都更新索引,那么它会大大降低速度

像Abe metioned一样:删除索引,然后重新创建 如果您信任您的数据:为每个对存储过程的调用生成一个sql语句,组合一些,然后执行。 这样可以节省通信开销。 对存储过程的组合调用可以包装在BEGIN事务中,因此每x次插入只有一个commit
如果这是一次性操作:不进行优化,并在夜间/周末运行它

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

数据是使用nText类型作为XML字符串传入的

类似的内容构成了执行该工作的存储过程的基本细节:

创建过程XMLInsertPr@XmlString ntext 声明@ReturnStatus int、@hdoc int

EXEC@ReturnStatus=sp_xml_preparedocument@hdoc OUTPUT,@XmlString 如果@ReturnStatus 0 开始 RAISERROR“无法打开XML文档”,16,150003 RETURN@ReturnStatus 终止 插入到表名中 从中选择*OPENXML@hdoc,带TableName的“/XMLData/Data”
结束

好,只是一个简短的提示,存储的过程。正在进行一些查找,而不是直接插入。解决此问题的正常方法是在插入之前进行查找。它不是完全事务性的,但是如果你要插入400万条记录,如果你能避免的话,你真的不应该以需要事务隔离的方式来做。正如您所描述的,我已经在多个场合使用过这种技术,甚至包括暂存表和存储过程。它工作得很好。假定查找不足以在处理传输时引起问题,则暂存表又好了一点。这确实很有效,我在将查找表加载到内存后进行了查找。谢谢。但是,关于查找,我正在传递一些应该从其他表中查找的ID,大约有7个查找。有时我会将XML数据插入临时表,然后执行任何需要的查找并将其添加到临时表中。temp表完成后,所有内容都将插入到主表中。这将加快插入主表的速度,从而减少锁定问题。或者,如果查找很快,insert语句上的一些附加SQL逻辑可以动态地获取它。这一切都取决于你对SQL的理解:dba会因为这个跟我发牢骚的:对不起。。。当我再看的时候,我的评论毫无意义。将删除它。@JeffSternal-使用这种方法,您对性能或需要注意的问题有何评论?尽管SQLBulkCopy可以工作,但它需要按照其他人的建议创建一个额外的表用于暂存。我更喜欢你的方法,出于某些原因,我宁愿避免额外的表格。SqlBulkCopy解决方案更可取,但它只支持在SQLServer上使用。这看起来像是一种方式,当这不是一个选项,例如MySQL