Raouf Chebri:PgBouncer:支持预处理语句的版本
内容提要
PgBouncer 1.22.0发布,提高查询吞吐量15%至250%,支持DEALLOCATE ALL和DISCARD ALL,以及1.21.0版本中发布的协议级预处理语句。PgBouncer是一个轻量级连接池,用于管理和维护数据库连接池,提高查询性能和安全性。
延伸解读
预处理语句的性能优势与适用场景
文章指出,预处理语句通过一次解析和生成执行计划,后续执行可更快。但这一优势在重复且繁重的数据库流量中更为明显。对于低频或一次性查询,性能提升可能有限。因此,是否使用预处理语句需结合实际负载评估,并非所有场景都能获得显著收益。
PgBouncer 对预处理语句的支持方式
PgBouncer 在协议层面支持预处理语句,这意味着直接使用 SQL 的 PREPARE 和 EXECUTE 命令无法通过 PgBouncer 工作。但客户端库通常封装了协议级支持,开发者可以像平常一样使用预处理语句,而无需显式调用 PREPARE。这要求开发者了解所用客户端库的具体用法。
PgBouncer 内部重写机制解析
PgBouncer 会检查客户端发送的预处理语句,为每个唯一查询字符串分配内部名称(如 PGBOUNCER_123),并在转发到 PostgreSQL 前重写命令。如果语句尚未在服务器上准备,PgBouncer 会先准备它。这一机制确保了连接池中预处理语句的正确性和复用性,同时减轻了服务器负担。
连接池与预处理语句的安全协同
预处理语句将数据值与查询结构分离,避免 SQL 注入攻击。结合 PgBouncer 的连接池,应用可以在高并发下保持安全。文章提到,Neon 项目默认提供直接和池化连接,池化连接使用 PgBouncer 并支持多达 10,000 个连接,这有助于克服 Postgres 默认连接数限制。
Q&A
PgBouncer 1.22.0 版本有哪些主要更新?
PgBouncer 1.22.0 将查询吞吐量提高了 15% 到 250%,并支持 DEALLOCATE ALL 和 DISCARD ALL,以及 1.21.0 版本中引入的协议级预处理语句。
Postgres 中的预处理语句是什么?
预处理语句是 Postgres 的一项功能,允许你一次创建并优化 SQL 查询,然后使用不同参数多次执行。它是一个模板,你定义查询结构,之后填入具体值。例如:PREPARE user_fetch_plan (TEXT) AS SELECT * FROM users WHERE username = $1; 然后 EXECUTE user_fetch_plan('alice');
使用预处理语句有什么好处?
预处理语句有两个主要好处:性能方面,SQL 语句只解析一次并生成执行计划,后续执行更快,在重复流量大的数据库中效果更明显;安全方面,可以避免 SQL 注入攻击,因为数据值与查询分开传输,不会被当作 SQL 执行。
PgBouncer 是什么?它解决了什么问题?
PgBouncer 是一个轻量级连接池,主要功能是管理和维护数据库连接池,以克服 Postgres 的连接限制。Postgres 为每个客户端连接创建独立的后端进程,当许多客户端连接时,内存需求增加。PgBouncer 通过保持活跃后端进程数量较低来解决这个问题。
如何在客户端库中使用 PgBouncer 的预处理语句?
PgBouncer 在协议级别支持预处理语句,因此 SQL 级别的 PREPARE 和 EXECUTE 不能直接使用。但大多数 PostgreSQL 客户端库支持预处理语句,通常抽象了显式的 PREPARE 和 EXECUTE。例如在 psycopg2 中:cur.execute(query, ('alice',), prepare=True);在 pg 中:client.query({name: 'fetch-user', text: 'SELECT * FROM users WHERE username = $1', values: ['alice']})。
PgBouncer 内部如何处理预处理语句?
PgBouncer 检查客户端发送的所有预处理语句查询,为每个唯一的查询字符串分配一个内部名称(如 PGBOUNCER_123)。在将命令转发给 Postgres 之前,PgBouncer 会重写使用预处理语句的每个命令,以使用匹配的内部名称。如果语句尚未在 PostgreSQL 服务器上准备,PgBouncer 会先准备它。