c# - 批量删除行。如何打开/重用 SQL Server 连接?

标签 c# sql-server dapper

如果我们要批量读取要删除的行,打开/使用 SQL Server 连接的最有效方法是什么?

foreach(IEnumerable<Log> logsPage in LogsPages)
{
    foreach(Log logEntry in logsPage)
    {
        // 1. get associated filenames
        // 2. delete row
        // 3. try delete each file
    }
}
  • 日志页面大小约为 5000 行
  • 与日志条目关联的文件的大小可能有所不同。我认为它们不会超过 500 Mb。
  • 我们使用 Dapper

我们应该让 Dapper 在 foreach 循环的每一步打开连接吗?我想 SQL Server 连接池就发生在这里?

或者我们应该为每个批处理打开一个显式连接?

最佳答案

如果您在紧密循环中执行多个数据库操作,通常最好在所有操作期间打开连接。在有争议的系统中,将连接返回到池中可能是有益的,因为在下一个数据库操作之前可能存在不确定的间隔,但是如果您正在执行大量顺序操作:不断地从数据库获取和返回连接池(并执行 sp_reset_connection,这发生在幕后)无缘无故地增加了开销。

所以明确地说,我将 Open[Async]() 放在 first foreach 上方。

注意:对于批处理,您可能会发现有一些方法可以减少往返次数,特别是使用 Dapper 中基于 id 的 IN 重写。既然您提到了 SQL-Server,这可以与将 SqlMapper.Settings.InListStringSplitCount 设置为正值(5、10 等是合理的选择;请注意,这是一个全局设置)相结合;例如,对于简单场景:

connection.Execute("delete from Foo where Id in @ids",
    new { ids = rows.Select(x => x.Id) });

比以下方式高效得多:

foreach (var row in rows)
{
    connection.Execute("delete from Foo where Id = @id",
        new { id = row.Id });
}

如果没有InListStringSplitCount,第一个版本将被重写为:

delete from Foo where Id in (@ids0, @ids1, @ids2, ..., @idsN)

使用InListStringSplitCount,第一个版本将被重写为:

delete from Foo where Id in (select cast([value] as int) from string_split(@ids,','))

它允许多次使用完全相同的查询,这有利于查询计划的重用。

关于c# - 批量删除行。如何打开/重用 SQL Server 连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64478316/

相关文章:

c# - 是否有可能在构造函数中违反 Liskov 替换原则?

c# - 在 ASP.NET MVC5 Web 应用程序中向用户帐户添加声明的正确方法

c# - 用 Dapper 调用自定义构造函数?

sql-server - 在 .NET Core 中的连接字符串之间轻松切换

c# - 在 MFC 应用程序中托管 Windows 窗体 (C#) (VC++,VS6.0)

c# - 独立存储中的绑定(bind)图像

sql-server - 为什么自定义 SSIS 日志提供程序不会显示在提供程序下拉列表中?

sql - 如何在sql server 2008中生成随机 bool 值?

sql-server - SQL Server 备份集 "Description"

c# - 查询映射的 CustomObject 时出现 NullPointerException