C# 向SQL数据库插入记录的更快方法
我有一个每小时在数据库中插入/更新数千条记录的工具。它将输入读入C# 向SQL数据库插入记录的更快方法,c#,sql,sql-server,for-loop,C#,Sql,Sql Server,For Loop,我有一个每小时在数据库中插入/更新数千条记录的工具。它将输入读入数据表,并逐行运行SQL命令: for(int i = 0; i < dataTable.Rows.Count; i++) { string sqlConnectionString = "server, db, user, pass, etc."; SqlConnection sqlDBConnection = new SqlConnection(sqlConnectionString);
数据表
,并逐行运行SQL命令:
for(int i = 0; i < dataTable.Rows.Count; i++)
{
string sqlConnectionString = "server, db, user, pass, etc.";
SqlConnection sqlDBConnection = new SqlConnection(sqlConnectionString);
string query = @"INSERT INTO table
(col1, col2, col3, etc.)
VALUES
(@col1, @col2, @col3, etc.)";
SqlCommand queryCommand = new SqlCommand(query, sqlDBConnection);
queryCommand.Parameters.Add("@col1", SqlDbType.Int);
queryCommand.Parameters["@col1"].Value = Convert.ToInt32(dataTable.Rows[i][0]);
queryCommand.Parameters.Add("@col2", SqlDbType.VarChar);
queryCommand.Parameters["@col2"].Value = dataTable.Rows[i][1].ToString();
queryCommand.Parameters.Add("@col3", SqlDbType.VarChar);
queryCommand.Parameters["@col3"].Value = dataTable.Rows[i][2].ToString();
sqlDBConnection.Open();
queryCommand.ExecuteNonQuery();
sqlDBConnection.Close();
}
for(int i=0;i
它工作得很好,但速度很慢。您有更快的解决方案吗?将批量插入与或一起使用。
这应该会加快速度这很慢,因为每个插入都是单独处理的,这会导致事务时间的开销。 尝试使用不同的方法进行批量插入。 无论是在框架上(比如SpringDataBulk),还是通过更改查询一次插入多个值
insert into table (col1, col2, col3, ...)
values (val1, val2, cal3, ...),
(val1, val2, cal3, ...),
(val1, val2, cal3, ...), ...
但是不要强迫所有人都不监督数据库连接的缓冲区大小。因为您的数据已经在数据表中,我认为最好的方法是使用。e、 g
为了更新现有记录,如果您使用SqlDataAdapter填充了DataTable,则可以使用该方法。如果不是,那么我建议在SQL中处理upsert。因为您使用的是SQL Server 2012,所以可以使用表值参数。第一步是创建您的 这应该与您的c#数据表具有相同的定义 然后,下一步是创建一个存储过程,该存储过程接受此类型作为参数,并根据是否存在匹配项,使用
MERGE
插入或更新记录:
CREATE PROCEDURE dbo.UpsertYourTable @Table dbo.YourTableType READONLY
AS
BEGIN
MERGE dbo.YourTable WITH (HOLDLOCK) AS t
USING @Table AS s
ON s.Col1 = t.Col1 -- OR HOWEVER YOU IDENTIFY EXISTING RECORDS
WHEN MATCHED THEN UPDATE
SET Col2 = Col2,
Col3 = Col4
WHEN NOT MATCHED THEN
INSERT (Col1, Col2, Col3, Col4)
VALUES (s.Col1, s.Col2, s.Col3, 'Test');
END;
GO
最后,要从c#调用此函数,您可以使用:
string sqlConnectionString = "server, db, user, pass, etc.";
using (var connection = new SqlConnection(sqlConnectionString))
using (var command = new SqlCommand("dbo.UpsertYourTable", connection))
{
command.CommandType = CommandType.StoredProcedure;
var tvp = new SqlParameter("@Table", SqlDbType.Structured);
tvp.Value = dataTable;
tvp.TypeName = "dbo.YourTableType";
command.Parameters.Add(tvp);
command.ExecuteNonQuery();
}
你有没有考虑过如何使用SSIS?或通过
批量插入
。无论您选择什么选项,您都希望最大限度地减少到db的连接数-一次数千次的呼叫将是密集的 不要为每个插件断开/连接。组一起插入到更大的事务中等+1在这方面,SQL批量复制是迄今为止最快的方法,如果您有架构并且可以自己增量生成ID,我个人每秒为批量复制完成20000多行。这里有一个可能有用的例子:这看起来不错。您是否知道如何加快更新现有记录的速度?也可以不使用例如col2列映射,但让我们假设将给定字符串写入col2中,如“test”?您不需要将此列添加到数据表中。您使用的是哪个版本的SQL Server?不建议使用Merge,因为它存在许多问题:默认情况下不会触发触发器,但您可以使用来启用它们,例如new SqlBulkCopy(sqlConnectionString,SqlBulkCopyOptions.FireTriggers)
CREATE PROCEDURE dbo.UpsertYourTable @Table dbo.YourTableType READONLY
AS
BEGIN
MERGE dbo.YourTable WITH (HOLDLOCK) AS t
USING @Table AS s
ON s.Col1 = t.Col1 -- OR HOWEVER YOU IDENTIFY EXISTING RECORDS
WHEN MATCHED THEN UPDATE
SET Col2 = Col2,
Col3 = Col4
WHEN NOT MATCHED THEN
INSERT (Col1, Col2, Col3, Col4)
VALUES (s.Col1, s.Col2, s.Col3, 'Test');
END;
GO
string sqlConnectionString = "server, db, user, pass, etc.";
using (var connection = new SqlConnection(sqlConnectionString))
using (var command = new SqlCommand("dbo.UpsertYourTable", connection))
{
command.CommandType = CommandType.StoredProcedure;
var tvp = new SqlParameter("@Table", SqlDbType.Structured);
tvp.Value = dataTable;
tvp.TypeName = "dbo.YourTableType";
command.Parameters.Add(tvp);
command.ExecuteNonQuery();
}