SQL Server+循环插入性能

本文关键字:性能 插入 循环 Server+ SQL | 更新日期: 2023-09-27 18:01:07

我正在进行如下所示的循环插入(方法a(,似乎用每个循环调用数据库不是一个好主意。我发现一个替代方案是在我的SProc中循环一个逗号分隔的字符串,而不是进行插入,这样数据库中就只有一个条目。在性能方面会有任何显著的改进吗?:

方法A:

foreach (DataRow row in dt.Rows) 
{
    userBll = new UserBLL();
    UserId = (Guid)row["UserId"];
    // Call userBll method to insert into SQL Server with UserId as one of the parameter.
}

方法B:

string UserIds = "Tom, Jerry, 007"; // Assuming we already concatenate the strings. So no loops this time here.
userBll = new UserBLL();  
// Call userBll method to insert into SQL Server with 'UserIds' as parameter.

方法B SProc/在SProc中执行循环插入

if right(rtrim(@UserIds ), 1) <> ','
    SELECT @string = @UserIds + ','
SELECT @pos =  patindex('%,%' , @UserIds )
while @pos <> 0 
begin
    SELECT @piece = left(@v, (@pos-1))
    -- Perform the insert here
    SELECT @UserIds = stuff(@string, 1, @pos, '')
    SELECT @pos =  patindex('%,%' , @UserIds )
end

SQL Server+循环插入性能

更少的查询通常意味着更快的处理。也就是说,我的一位同事在这方面取得了一些成功。NET Framework的TSQL BULK INSERT包装器,该包装器由Framework提供为SqlBulkCopy。这个MSDN博客展示了如何使用它。

主要的"API"示例如下(取自链接文章as-is,它将DataTable的内容写入SQL(:

private void WriteToDatabase()
{
    // get your connection string
    string connString = "";
    // connect to SQL
    using (SqlConnection connection = 
            new SqlConnection(connString))
    {
        // make sure to enable triggers
        // more on triggers in next post
        SqlBulkCopy bulkCopy = 
            new SqlBulkCopy
            (
            connection, 
            SqlBulkCopyOptions.TableLock | 
            SqlBulkCopyOptions.FireTriggers | 
            SqlBulkCopyOptions.UseInternalTransaction,
            null
            );
        // set the destination table name
        bulkCopy.DestinationTableName = this.tableName;
        connection.Open();
        // write the data in the "dataTable"
        bulkCopy.WriteToServer(dataTable);
        connection.Close();
    }
    // reset
    this.dataTable.Clear();
    this.recordCount = 0;
}

链接的文章解释了利用这一机制需要做些什么。

根据我的经验,有三件事你不想为每条记录做:

  1. 每行打开/关闭一个sql连接。这个问题由ADO处理。NET连接池。除非您禁用了池,否则您不必担心它。

  2. 每行的数据库往返。这往往与网络带宽或网络延迟无关,而与客户端线程睡眠有关。每次客户端醒来时,你都需要在客户端上做大量的工作,或者你在浪费时间。

  3. 按行打开/关闭sql事务日志。打开和关闭日志不是免费的,但你也不想打开太久。在一个事务中执行多个插入,但不要太多。

对于其中的任何一个,您可能会看到从每个请求1行到每个请求10行的许多改进。您可以通过在传输批处理之前在客户端构建10个插入语句来实现这一点。

Sommarskog已经对你将列表发送到进程中的方法进行了深入的研究。

如果您想在给定类型的多个输入值中获得更好的插入性能,我建议您查看表值参数。

这里可以找到一个示例,显示了一些使用它们的示例代码。

您可以为此使用批量插入功能。

有关详细信息,请参阅此博客:http://blogs.msdn.com/b/nikhilsi/archive/2008/06/11/bulk-insert-into-sql-from-c-app.aspx