报错是这么冒出来的。压测时用 SET hnsw.ef_search = 100 之后单条查询召回正常,服务跑起来召回又回到默认的 40,客户端连的是 PgBouncer 1.21 的 transaction 模式,配置里没写过这个参数。
中间走过弯路,把「连接初始化 SQL 里设过,池子的 server_reset_query 又把参数重置回去」当成主因,改完现象没变。
原因不止一个,得分开看。SET 的作用域是当前会话,事务模式连接池每个事务换一条连接,设置随之丢失。也可能是代码里写成 SET LOCAL,事务一提交就恢复,长连接也留不住。
还有一种情况,参数拼在连接串 options 里,pgbouncer 不转发给后端。
动手时先确认当前会话里参数实际取到的值
psql "postgresql://kb@127.0.0.1:6432/kb" -c "SHOW hnsw.ef_search;"
接着把默认值设到库级,让新连接直接继承
psql -d kb -c "ALTER DATABASE kb SET hnsw.ef_search = 100;"
给应用角色也设一份,避免换库就失效
psql -d kb -c "ALTER ROLE kb_app SET hnsw.ef_search = 100;"
压测脚本里逐条核对实际生效值
python -c "import psycopg;print(psycopg.connect('dbname=kb').execute('SHOW hnsw.ef_search').fetchone())"
别只看报错消失,验证要多做一步。SHOW 返回 100,压测 recall@10 从 0.71 升到 0.93,pg_stat_activity 里新连接的参数与库级默认一致。
提醒一点。ef_search 越大延迟越高,按 top_k 的十倍设通常够用,再往上加召回收益很小但延迟涨得快。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。
