Postgresql-准备语句与连接池-这是一种折衷吗?

Postgresql-准备语句与连接池-这是一种折衷吗?,postgresql,prepared-statement,connection-pooling,npgsql,pgbouncer,Postgresql,Prepared Statement,Connection Pooling,Npgsql,Pgbouncer,我的理解是,您可以将准备好的语句或连接池与Postgresql中的pgPool/pgBouncer等工具一起使用,但同时只能从中受益。我说得对吗? 如果是的话——对于其他运行时和语言,比如Java、Python、Go,这是真的吗?或者这是一个特定于实现的问题?我认为这是一个一般性的问题,所以我将给出一个一般性的答案。适用于特定连接池实现的方面可能会有所不同 有几种连接池模式: 线程在会话池期间保留连接: 在这种情况下,可以在会话期间保持像prepared语句这样的持久状态,但是当会话返回到池时,

我的理解是,您可以将准备好的语句或连接池与Postgresql中的pgPool/pgBouncer等工具一起使用,但同时只能从中受益。我说得对吗?
如果是的话——对于其他运行时和语言,比如Java、Python、Go,这是真的吗?或者这是一个特定于实现的问题?

我认为这是一个一般性的问题,所以我将给出一个一般性的答案。适用于特定连接池实现的方面可能会有所不同

有几种连接池模式:

线程在会话池期间保留连接: 在这种情况下,可以在会话期间保持像prepared语句这样的持久状态,但是当会话返回到池时,应该清除该状态

线程在数据库事务池期间保留连接: 在这种情况下,您必须在每个事务之后清除状态,因此准备好的语句没有多大意义

线程在语句轮询期间保留连接: 这只在非常有限的情况下有用,您不需要跨越多条语句的事务。显然,像预处理语句这样的状态是无法共享的

这取决于您使用的连接池类型。基本上,线程保留连接的时间越长,使用准备好的语句就越有意义


当然,如果您知道自己在做什么,也可以在数据库连接建立之后立即创建一个准备好的语句,并且永远不要取消分配它。只有当所有线程都需要相同的准备语句时,这才有效。这样的设置很容易出错。

我认为这是一个一般性的问题,所以我会给出一个一般性的答案。适用于特定连接池实现的方面可能会有所不同

有几种连接池模式:

线程在会话池期间保留连接: 在这种情况下,可以在会话期间保持像prepared语句这样的持久状态,但是当会话返回到池时,应该清除该状态

线程在数据库事务池期间保留连接: 在这种情况下,您必须在每个事务之后清除状态,因此准备好的语句没有多大意义

线程在语句轮询期间保留连接: 这只在非常有限的情况下有用,您不需要跨越多条语句的事务。显然,像预处理语句这样的状态是无法共享的

这取决于您使用的连接池类型。基本上,线程保留连接的时间越长,使用准备好的语句就越有意义


当然,如果您知道自己在做什么,也可以在数据库连接建立之后立即创建一个准备好的语句,并且永远不要取消分配它。只有当所有线程都需要相同的准备语句时,这才有效。这样的设置很容易出错。

这是一个复杂的问题,但这里有一些答案

正如@laurenz albe所写,您可以使用pgbouncer和prepared语句,但需要使用会话池。这允许您在连接期间使用准备好的语句,即只要NpgsqlConnection实例处于打开状态。但是,如果您处于短期连接场景中,例如web应用程序为每个HTTP请求打开和关闭连接,那么您就不走运了。从这个意义上讲,可以说池语句和准备语句是不兼容的

但是,如果您在默认情况下在上使用Npgsql的内部池机制,而不是pgbouncer,则准备好的语句会在连接打开/关闭时自动持久化。换句话说,当您调用NpgsqlCommand.Prepare时,如果物理连接碰巧已经准备好了SQL,那么将重用准备好的语句。这样做的目的是为了在短期连接场景中释放预处理语句的速度优势。这是Npgsql非常独特的行为


这是进程内连接池的优点之一,与进程外连接池(如pgbouncer)相比,Npgsql在物理连接传递时保留有关该连接的信息,在本例中,是一个表,其中的语句是name和SQL。

这是一个复杂的问题,但这里有一些答案

正如@laurenz albe所写,您可以使用pgbouncer和prepared语句,但需要使用会话池。这允许您在连接期间使用准备好的语句,即只要NpgsqlConnection实例处于打开状态。但是,如果您处于短期连接场景中,例如web应用程序为每个HTTP请求打开和关闭连接,那么您就不走运了。从这个意义上说,可以这样说 池和准备好的语句不兼容

但是,如果您在默认情况下在上使用Npgsql的内部池机制,而不是pgbouncer,则准备好的语句会在连接打开/关闭时自动持久化。换句话说,当您调用NpgsqlCommand.Prepare时,如果物理连接碰巧已经准备好了SQL,那么将重用准备好的语句。这样做的目的是为了在短期连接场景中释放预处理语句的速度优势。这是Npgsql非常独特的行为


这是进程内连接池的优点之一,与进程外连接池(如pgbouncer)相比,Npgsql在传递物理连接时保留了有关该连接的信息,在本例中,保留了一个表,其中的语句是name和SQL。

因此,我的第一个问题的答案是它取决于什么?我这么说,是的。那么我的第一个问题的答案是这要视情况而定吗?我会这么说,是的。