supavisor icon indicating copy to clipboard operation
supavisor copied to clipboard

Support named prepared statements

Open chasers opened this issue 2 years ago • 13 comments

No pooler currently supports named prepared statements. Lots of SQL clients which use their own pool do e.g. Elixir's Ecto uses named prepared statements by default and ships with it's own pooling logic.

It seems reasonable for a pooler to be able to support them. Named prepared statements can increase throughput significantly because the query plan is cached.

Unnamed prepared statements do not use a cached query plan because it is deallocated with the next unnamed prepared statement.

If successfully created, a named prepared-statement object lasts till the end of the current session, unless explicitly destroyed. An unnamed prepared statement lasts only until the next Parse statement specifying the unnamed statement as destination is issued. ref

Questions

What if two different clients linked to one pg connection make two different prepared statements with the same name?

Because it's an async protocol can we add metadata to messages that Postgres will include coming back? Then we can use that to route the right messages to the right clients.

Can we use pipelining to multiplex?

Ideas

  • Another pool mode
  • Pin a client connection to a db conn such that each client would always get the same db conn from the pool

There would be some contention here probably because clients would have to wait on a specific conn but it would work. Question is does the contention negate the perf from the prepared statement. With another mode transaction pooling would work as expected but you could use this new mode if it works for your workload and provides perf gains.

chasers avatar Apr 11 '23 15:04 chasers

What if two different clients linked to one pg connection make two different prepared statements with the same name?

To clarify this case: We generally want both clients to use the same prepared statement. A classic "one process per request" infrastructure often means thousands of client connections and hundreds of server connections. Let's assume 10:1. If each of those processes handles 100 requests before getting cycled, then a given query used once in each request would use 5 custom plans and 95 generic plans for a 95% cache hit rate. If that prepared_statement is available to all clients using that server connection then we'd instead see a 99.5% hit rate.

hamiltop avatar Apr 11 '23 22:04 hamiltop

For sure. I think it really depends on how the client handles things though. Do they recreate the prepared statement on a connection if it doesn't exist? How do they name them?

I'm thinking a separate pool mode which pins client connections to database connections would be good. So transaction mode behaves exactly like PgBouncer transaction mode and you could use this other mode if it's suitable for your workload and provides perf improvements.

chasers avatar Apr 12 '23 15:04 chasers

For reference: a PR for pgbouncer that claims to make things work: https://github.com/pgbouncer/pgbouncer/pull/757#how-it-works

hamiltop avatar Apr 12 '23 21:04 hamiltop

Very helpful! Thank you!

chasers avatar Apr 13 '23 00:04 chasers

Another ref

chasers avatar Jun 23 '23 15:06 chasers

I personally think this would be an important issue to fix due to some client libraries rely on this to work properly, such as Rust's SQLx, at the moment it seems like only pgcat supports it.

marcustut avatar Oct 12 '23 19:10 marcustut

PgBouncer actually just merged support for this: https://github.com/pgbouncer/pgbouncer/pull/845 (Not released yet, but in main branch)

janpio avatar Oct 13 '23 18:10 janpio

PgBouncer actually just merged support for this: https://github.com/pgbouncer/pgbouncer/pull/845 (Not released yet, but in main branch)

Would this be released on existing Supabase's cloud hosted databases? I would really like to use it with my Supabase database, it is currently using supavisor as its connection pool.

marcustut avatar Oct 14 '23 20:10 marcustut

+1 for this since pgbouncer has a solution and since supabase forces you to use supavisor now it seems to be worth wild to add

softwarecurator avatar Nov 05 '23 05:11 softwarecurator

Done, and deployed to production!!

chasers avatar Dec 23 '23 15:12 chasers

I feel like this issue should probably be re-opened given that this doesn't add support for protocol level named prepared statements (which are the ones that basically all client libraries use). Related issue and my comment there can be found here: https://github.com/supabase/supavisor/issues/239#issuecomment-2112440255

JelteF avatar May 15 '24 14:05 JelteF

from v0idpwn:

Implemented this in #694, behind a feature flag. After further validation will enable for everyone.

linear[bot] avatar Sep 17 '25 16:09 linear[bot]

Hi @v0idpwn, do you have a rough schedule for enabling this on Supabase's shared pooler?

l2dy avatar Nov 04 '25 16:11 l2dy