批量删除行。如何打开/重用 SQL 服务器连接?
Deleting rows by batches. How to open / reuse SQL Server connection?
如果我们正在读取要分批删除的行,open/use SQL 服务器连接的最有效方法是什么?
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 服务器连接池发生在这里?
或者我们应该每批打开一个显式连接?
如果您在紧密循环中执行多个数据库操作,通常最好在所有操作期间打开连接。在下一次数据库操作之前可能有 不确定 间隔的竞争系统中,将连接返回到池中可能是有益的,但是如果您正在执行大量顺序操作:不断获取和返回来自池的连接(并执行 sp_reset_connection
,这发生在幕后)无缘无故地增加了开销。
明确地说,我会在第一个 foreach
.
上方添加Open[Async]()
注意:对于批处理,您可能会发现有一些方法可以用更少的 round-trips 来完成此操作,特别是在基于 ID 的 Dapper 中使用 IN
re-writing .既然你提到了 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
,第一个版本将是 re-written,例如:
delete from Foo where Id in (@ids0, @ids1, @ids2, ..., @idsN)
使用 InListStringSplitCount
,第一个版本将是 re-written,例如:
delete from Foo where Id in (select cast([value] as int) from string_split(@ids,','))
允许多次使用完全相同的查询,这对 query-plan re-use.
很有用
如果我们正在读取要分批删除的行,open/use SQL 服务器连接的最有效方法是什么?
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 服务器连接池发生在这里?
或者我们应该每批打开一个显式连接?
如果您在紧密循环中执行多个数据库操作,通常最好在所有操作期间打开连接。在下一次数据库操作之前可能有 不确定 间隔的竞争系统中,将连接返回到池中可能是有益的,但是如果您正在执行大量顺序操作:不断获取和返回来自池的连接(并执行 sp_reset_connection
,这发生在幕后)无缘无故地增加了开销。
明确地说,我会在第一个 foreach
.
Open[Async]()
注意:对于批处理,您可能会发现有一些方法可以用更少的 round-trips 来完成此操作,特别是在基于 ID 的 Dapper 中使用 IN
re-writing .既然你提到了 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
,第一个版本将是 re-written,例如:
delete from Foo where Id in (@ids0, @ids1, @ids2, ..., @idsN)
使用 InListStringSplitCount
,第一个版本将是 re-written,例如:
delete from Foo where Id in (select cast([value] as int) from string_split(@ids,','))
允许多次使用完全相同的查询,这对 query-plan re-use.
很有用