0

我正在执行如下所示的循环插入(方法 A),似乎用每个循环调用数据库并不是一个好主意。我发现另一种方法是在我的 SProc 中循环一个逗号分隔的字符串,而不是执行插入操作,以便只有一个数据库条目。在性能方面会有任何显着改善吗?:

方法一:

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
4

4 回答 4

1

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

主要的“API”示例是这样的(取自链接的文章,它将 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;
}

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

于 2013-02-26T15:03:33.043 回答
1

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

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

  2. 每行的数据库往返。这往往与网络带宽或网络延迟无关,而与客户端线程休眠有关。每次唤醒时,您都希望在客户端进行大量工作,或者您正在浪费时间片。

  3. 打开/关闭每行的 sql 事务日志。打开和关闭日志不是免费的,但你也不想让它打开太久。在单个事务中进行多次插入,但不要太多。

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

您将列表发送到 proc 的方法已由Sommarskog进行了极其深入的描述。

于 2013-02-26T15:11:43.563 回答
0

如果您正在寻找具有给定类型的多个输入值的更好插入性能,我建议您查看table valued parameters

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

于 2013-02-26T14:58:11.183 回答
0

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

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

于 2013-02-26T15:05:28.287 回答