我的理解是,你可以在PostgreSQL中使用准备好的语句或连接池(使用pgPool/pgBouncer这样的工具),但同时只能从一个(at least with Npgsql driver for .NET,加上library author suggests turning off clients-side connection pooling when using PgBouncer)中受益。
如果是这样的话,这对其他运行时和语言(如Java、Python、Go)也是如此吗?或者这是一个特定于实现的问题?
3条答案
按热度按时间svmlkihl1#
这是一个复杂的问题,但这里有一些答案。
正如@laurenz-albe所写的,您可以使用pgbouncer和预准备语句,但需要使用会话池。(即,只要您的NpgsqlConnection示例处于打开状态)。但是,如果您处于短期连接场景中,(例如,web应用程序为每个HTTP请求打开和关闭连接),你运气不好。从这个意义上说,可以说池和准备语句不兼容。
但是,如果使用Npgsql的内部池机制,(默认情况下为on)而不是pgbouncer,那么你的准备好的语句会在连接打开/关闭时自动持久化。换句话说,当你调用
NpgsqlCommand.Prepare()
时,如果物理连接碰巧已经准备好了SQL,那么预处理语句将被重用。这样做是为了释放预处理语句的速度优势,live connection scenarios.这是Npgsql的一个非常独特的行为,请参阅文档以获取更多信息。这是进程内连接池的优点之一,与进程外连接池(如pgbouncer)相反- Npgsql在传递物理连接时保留有关物理连接的信息,在本例中是准备语句(名称和SQL)的表。
qvtsj1bj2#
我认为这是一个一般性的问题,所以我将给予一个一般性的答案。什么方面适用于特定的连接池实现可能会有所不同。
连接池有几种模式:
在这种情况下,可以在会话期间保持像预准备语句这样的持久状态,但是应该在会话返回到池时清除状态。
在这种情况下,您必须在每个事务之后清理状态,因此预准备语句没有多大意义。
这只在非常有限的情况下才有用,在这种情况下,你不需要跨多个语句的事务。显然,没有像准备好的语句这样的状态可以共享。
这取决于你使用哪种连接池。基本上,线程保持连接的时间越长,使用预处理语句就越有意义。
当然,如果你知道你在做什么,你也可以在数据库连接建立后立即创建一个准备好的语句,并且永远不释放它。这只有在所有线程都需要相同的准备好的语句时才有效。这样的设置很容易搞砸。
ijnw1ujt3#
从PgBouncer 1.21.0开始,它现在支持在事务池模式下的协议级别命名的准备语句。所以它不再是一个折衷,你可以同时使用这两个。你可以通过在PgBouncer的配置文件中将
max_prepared_statements
设置为非零值来打开这个支持。有关详细信息,请查看文档:https://www.pgbouncer.org/config.html#max_prepared_statements