Postgresql -准备语句与连接池-这是一个权衡?

cuxqih21  于 2023-11-18  发布在  PostgreSQL
关注(0)|答案(3)|浏览(142)

我的理解是,你可以在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)也是如此吗?或者这是一个特定于实现的问题?

svmlkihl

svmlkihl1#

这是一个复杂的问题,但这里有一些答案。
正如@laurenz-albe所写的,您可以使用pgbouncer和预准备语句,但需要使用会话池。(即,只要您的NpgsqlConnection示例处于打开状态)。但是,如果您处于短期连接场景中,(例如,web应用程序为每个HTTP请求打开和关闭连接),你运气不好。从这个意义上说,可以说池和准备语句不兼容。
但是,如果使用Npgsql的内部池机制,(默认情况下为on)而不是pgbouncer,那么你的准备好的语句会在连接打开/关闭时自动持久化。换句话说,当你调用NpgsqlCommand.Prepare()时,如果物理连接碰巧已经准备好了SQL,那么预处理语句将被重用。这样做是为了释放预处理语句的速度优势,live connection scenarios.这是Npgsql的一个非常独特的行为,请参阅文档以获取更多信息。
这是进程内连接池的优点之一,与进程外连接池(如pgbouncer)相反- Npgsql在传递物理连接时保留有关物理连接的信息,在本例中是准备语句(名称和SQL)的表。

qvtsj1bj

qvtsj1bj2#

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

  • 线程在会话期间保持连接(会话池):

在这种情况下,可以在会话期间保持像预准备语句这样的持久状态,但是应该在会话返回到池时清除状态。

  • 线程在数据库事务期间保持连接(事务池):

在这种情况下,您必须在每个事务之后清理状态,因此预准备语句没有多大意义。

  • 一个线程在一个语句的持续时间内保留一个连接(语句轮询):

这只在非常有限的情况下才有用,在这种情况下,你不需要跨多个语句的事务。显然,没有像准备好的语句这样的状态可以共享。
这取决于你使用哪种连接池。基本上,线程保持连接的时间越长,使用预处理语句就越有意义。
当然,如果你知道你在做什么,你也可以在数据库连接建立后立即创建一个准备好的语句,并且永远不释放它。这只有在所有线程都需要相同的准备好的语句时才有效。这样的设置很容易搞砸。

ijnw1ujt

ijnw1ujt3#

从PgBouncer 1.21.0开始,它现在支持在事务池模式下的协议级别命名的准备语句。所以它不再是一个折衷,你可以同时使用这两个。你可以通过在PgBouncer的配置文件中将max_prepared_statements设置为非零值来打开这个支持。有关详细信息,请查看文档:https://www.pgbouncer.org/config.html#max_prepared_statements

相关问题