繁体   English   中英

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

[英]Deleting rows by batches. How to open / reuse SQL Server connection?

如果我们要批量读取要删除的行,打开/使用 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]()放在第一个foreach之上。

注意:对于批处理,您可能会发现有一些方法可以减少往返次数,特别是利用基于 id 的 Dapper 中的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,','))

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM