feat: rewrite simple to prepared - #1346
Conversation
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
| if let Some(ref step_two) = self.step_two { | ||
| request.simple_to_prepared_rewrite = true; | ||
| request.clear(); | ||
| request.push(ProtocolMessage::Parse(step_two.parse.clone())); |
There was a problem hiding this comment.
is this rewrite will later lead to prepare_statement consider it's like usual Parse and cause the same global cache check later? I guess it'll be the same name anyway if we get the same query transform anyway..
There was a problem hiding this comment.
Yeah, so Server will see this, check its cache, if it's already prepared, it will skip (drop, add_ignore('1')). If not, it will add to its local cache and send the Parse to pg.
There was a problem hiding this comment.
Strangely I'm seeing no performance improvements from this...in fact, this branch is a bit slower than main...
|
I might kick this one down the road. It's kinda too complicated and introduces side effects:
|
|
I put this through a proper Forge run to understand the “no improvement / slightly slower” result. This was not a quick local pgbench sample. Method
Result
Feature-on was 2.12% below the same binary with it off, and 1.80% below base, by medians. The on range overlaps the controls, so Forge's strict slowdown claim is inconclusive rather than proven. But the “no reliable improvement, slightly slower median” observation does reproduce. The mechanism is much less ambiguous:
So PostgreSQL is reusing the prepared statement successfully. The issue is that almost all of the ~0.140 ms saved in PostgreSQL is replaced by ~0.116 ms of extra measured PgDog AST/rewrite/deparse work, before counting the remaining protocol/cache/message overhead. The perf profiles show the CPU work moving tiers:
Feature-on-specific hot symbols include literal replacement, deparse routines, AST allocation, vector/message cloning, and hashing. This lines up with the implementation: simple queries deliberately bypass the AST cache; each request transforms literals and deparses the statement; the historical implementation takes a global prepared-cache write; and it builds a Parse/Describe/Bind/Execute/Sync sequence on every request. One useful control: a later branch commit ( My read: the idea works and the server-side mechanism is proven, but for the historical parser-stress workload the spike mostly moves planning CPU from PostgreSQL into PgDog and adds enough cache/protocol work to erase the gain. I kept the complete Forge run artifacts, raw measurements, system streams, and perf data locally if we want to turn this into a committed regression case. |
|
Cool. So I would maybe use this as a "we can't enable prepared statements" but we need to because of X. Not sure what X is though. |
closes #1313