Npgsql 和 async 的并发连接数
Number of concurrent connections with Npgsql and async
我正在尝试最大化 PostgreSQL 数据库的吞吐量,通过从线程池迁移到异步查询可以获得巨大的性能飞跃。这是将执行所述查询的代码的 async
版本:
using (var conn = new NpgsqlConnection(connStr)) {
await conn.OpenAsync();
var id = await conn.ExecuteScalarAsync<long>(
"my_proc",
param_obj,
commandType: CommandType.StoredProcedure,
commandTimeout: 0
);
return id;
}
以前,在使用线程池时,我可以通过简单地设置线程数来设置任何给定时间的最大打开连接数(如果我超过了 MaxPoolSize,我会看到池耗尽/超时异常,因为预期的)。但是在这种情况下,连接数不会很快爆炸吗?也许有一种我不知道的更规范的方法。
您的代码是异步的这一事实不会(就其本身)以任何方式改变连接池的工作,也不会(再次,就其本身)更快地耗尽连接池。在 OpenAsync() 完成(异步)的那一刻,一个连接已从池中分配给您的代码,并且在它被释放之前将被视为繁忙。这与同步代码中的工作方式没有根本区别;唯一的区别是,在同步版本中,所有 I/O 上都有一个线程阻塞,但在异步版本中没有。
现在,在您以前的同步版本中,您似乎是通过设置执行数据库代码的线程数来控制并发打开的连接数。由于使用异步,一旦有 I/O,线程就会产生,这显然是不相关的。相反,您可以简单地控制(同时)调用上述代码的次数。例如,您可以 运行 100 个参数值的代码,然后使用 Task.WhenAny()
等待这些操作中的任何一个完成。当发生这种情况时,您可以执行另一个任务(使用新的参数值),依此类推。
我正在尝试最大化 PostgreSQL 数据库的吞吐量,通过从线程池迁移到异步查询可以获得巨大的性能飞跃。这是将执行所述查询的代码的 async
版本:
using (var conn = new NpgsqlConnection(connStr)) {
await conn.OpenAsync();
var id = await conn.ExecuteScalarAsync<long>(
"my_proc",
param_obj,
commandType: CommandType.StoredProcedure,
commandTimeout: 0
);
return id;
}
以前,在使用线程池时,我可以通过简单地设置线程数来设置任何给定时间的最大打开连接数(如果我超过了 MaxPoolSize,我会看到池耗尽/超时异常,因为预期的)。但是在这种情况下,连接数不会很快爆炸吗?也许有一种我不知道的更规范的方法。
您的代码是异步的这一事实不会(就其本身)以任何方式改变连接池的工作,也不会(再次,就其本身)更快地耗尽连接池。在 OpenAsync() 完成(异步)的那一刻,一个连接已从池中分配给您的代码,并且在它被释放之前将被视为繁忙。这与同步代码中的工作方式没有根本区别;唯一的区别是,在同步版本中,所有 I/O 上都有一个线程阻塞,但在异步版本中没有。
现在,在您以前的同步版本中,您似乎是通过设置执行数据库代码的线程数来控制并发打开的连接数。由于使用异步,一旦有 I/O,线程就会产生,这显然是不相关的。相反,您可以简单地控制(同时)调用上述代码的次数。例如,您可以 运行 100 个参数值的代码,然后使用 Task.WhenAny()
等待这些操作中的任何一个完成。当发生这种情况时,您可以执行另一个任务(使用新的参数值),依此类推。