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

莱克美

如果我们正在读取要分批删除的行,那么打开/使用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

注意:对于批处理,您可能会发现有一些方法可以减少往返次数,尤其是利用IN基于ID的Dapper重写。由于您提到了SQL Server,因此可以将a设置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,','))

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章