Skip to content

perf: migrate to unnest (from VALUES) for CTEs, INSERT .. SELECT FROM, SELECT/UPDATE FROM - #2003

Draft
jkaczman wants to merge 3 commits into
jk-unnest-select-targetsfrom
jk-subqueries-repl-values-w-unnest
Draft

jkaczman wants to merge 3 commits into
jk-unnest-select-targetsfrom
jk-subqueries-repl-values-w-unnest

Conversation

@jkaczman

@jkaczman jkaczman commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

Works off the previous changes implementing splitting INSERT with unnest (#1988, #2000) to now implement this unnest functionality to be used when re-writing subqueries (as opposed to re-writing the SQL to have an explicit VALUES clause with all the DataRows inlined) when we send the subquery data rows back to Postgres in the outer statement to be evaluated.

This should be a considerable speedup vs. before; if we had 10,000 DataRows returned, it's much cheaper to include the data in an array in a Bind parameter vs. creating a new SQL statement with 10,000 tuples and deparsing it.

Not handled for WHERE clause yet. Will follow up.

@jkaczman
jkaczman added this pull request to stack #1986 November 9, 2026 21:21
@jkaczman
jkaczman force-pushed the jk-subqueries-repl-values-w-unnest branch from b31ce78 to 3b31f94 Compare November 9, 2026 21:34
@github-actions

github-actions Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Metal bench (arm64) failed. 1 of 475 measures outside bounds.

suite throughput cpu/txn user cycles/txn user instr/txn kernel cycles/txn kernel instr/txn ctx/txn
pooler 18.66 (+0.5% ± 0.5%) 18,010 (+0.9% ± 0.2%) 32,033 (+0.0% ± 0.05%) 29,541 (+0.2% ± 0.7%) 51,220 (-0.1% ± 0.6%)
lb 19.38 (+0.9% ± 0.8%) 18,603 (+1.2% ± 0.2%) 32,931 (+0.0% ± 0.04%) 30,577 (+0.4% ± 1.4%) 52,285 (-0.3% ± 0.3%)
sharding-w2 33.8 (+1.4% ± 0.4%) 46,143 (+1.4% ± 2.0%) 97,463 (+0.1% ± 0.08%) 41,933 (+1.0% ± 1.3%) 53,565 (-0.0% ± 0.06%) 1.539 (-0.1% ± 0.3%)
sharding-w8 241,425 (-0.6% ± 1.2%) 29.77 (+0.5% ± 1.2%) 45,637 (+0.3% ± 1.1%) 52,979 (+0.1% ± 0.02%) 36,642 (+0.7% ± 2.0%) 42,387 (+0.0% ± 0.03%) 0.1651 (+1.1% ± 2.1%)
Counters per txn
suite frontend stall l1i refill backend stall
pooler 7,170 (+0.4% ± 0.5%) 2,585 (+0.2% ± 0.3%)
lb 7,476 (+1.0% ± 0.9%) 2,640 (+0.6% ± 0.2%)
sharding-w2 19,842 (+2.6% ± 6.7%) 4,290 (+0.5% ± 4.6%)
sharding-w8 21,162 (-1.4% ± 2.7%) 4,201 (-1.0% ± 1.1%)
benchmark measure result baseline change bound
full_simple::aggregate instructions 148,635 147,114 +1.03% ± 0.00% +1%

Microbench: 461 of 462 measures within bounds.

Hot code per txn
path base head change
pooler 111.2 KB 111.8 KB +0.6 KB
sharding-w2 166.2 KB 165.0 KB -1.2 KB

pooler:

crate base head change
pgdog::frontend::client::query_engine 19.8 KB 19.7 KB -0.1 KB
tokio 18.4 KB 18.2 KB -0.1 KB
pgdog::backend::pool 17.4 KB 17.4 KB +0.0 KB
aws-lc (TLS crypto) 10.2 KB 10.4 KB +0.2 KB
rustls (TLS) 8.4 KB 8.5 KB +0.1 KB
pgdog::frontend (other) 7.8 KB 7.9 KB +0.1 KB
pgdog::backend::server 7.2 KB 7.1 KB -0.1 KB
other 6.4 KB 6.6 KB +0.2 KB
everything else 15.8 KB 16.0 KB +0.2 KB
function head change
pgdog::frontend::client::Client::run::{{closure}} 5.5 KB +0.2 KB
pgdog::frontend::client::query_engine::query::<impl pgdog::frontend::client::query_engine: 5.3 KB -0.1 KB
pgdog::frontend::client::query_engine::QueryEngine::handle::{{closure}} 4.0 KB -0.1 KB
tokio::runtime::task::raw::poll 3.2 KB +0.0 KB
pgdog::frontend::client::query_engine::query::<impl pgdog::frontend::client::query_engine: 2.9 KB +0.0 KB

sharding-w2:

crate base head change
pgdog::frontend::router 28.7 KB 29.2 KB +0.6 KB
pgdog::frontend::client::query_engine 21.2 KB 21.2 KB +0.0 KB
tokio 18.6 KB 18.4 KB -0.2 KB
pgdog::backend::pool 18.2 KB 18.1 KB -0.1 KB
aws-lc (TLS crypto) 12.9 KB 12.9 KB -0.1 KB
other 9.9 KB 9.9 KB +0.1 KB
pgdog::frontend (other) 8.5 KB 8.6 KB +0.1 KB
rustls (TLS) 8.1 KB 8.1 KB -0.1 KB
everything else 40.1 KB 38.5 KB -1.6 KB
function head change
pgdog::frontend::client::Client::run::{{closure}} 6.2 KB +0.2 KB
pgdog::frontend::client::query_engine::query::<impl pgdog::frontend::client::query_engine: 5.4 KB -0.1 KB
pgdog::frontend::client::query_engine::QueryEngine::handle::{{closure}} 4.2 KB +0.0 KB
pgdog::frontend::router::parser::query::select::<impl pgdog::frontend::router::parser::que 3.4 KB +0.1 KB
tokio::runtime::task::raw::poll 3.1 KB -0.1 KB
lb flamegraph vs df1af3b

lb

Open interactive for hover, zoom and search.

lb removed

Open interactive.

microbench flamegraph vs df1af3b

microbench

Open interactive for hover, zoom and search.

microbench removed

Open interactive.

pooler flamegraph vs df1af3b

pooler

Open interactive for hover, zoom and search.

pooler removed

Open interactive.

sharding-w2 flamegraph vs df1af3b

sharding-w2

Open interactive for hover, zoom and search.

sharding-w2 removed

Open interactive.

sharding-w8 flamegraph vs df1af3b

sharding-w8

Open interactive for hover, zoom and search.

sharding-w8 removed

Open interactive.

Logs

lb, microbench, pooler, sharding-w2, sharding-w8, verdict.json

Compared 6109875 with df1af3b on m8g.metal-24xl (spot).

@github-actions

github-actions Bot commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

Metal bench (x86) failed. 1 of 475 measures outside bounds.

suite throughput cpu/txn user cycles/txn user instr/txn kernel cycles/txn kernel instr/txn ctx/txn
pooler 34.63 (-1.3% ± 0.2%) 22,685 (-4.5% ± 0.4%) 33,903 (+0.1% ± 0.02%) 57,782 (-0.3% ± 0.4%) 38,549 (+0.2% ± 0.05%)
lb 35.63 (-1.5% ± 0.2%) 23,884 (-5.2% ± 0.6%) 34,856 (+0.1% ± 0.03%) 58,642 (-0.4% ± 0.2%) 39,227 (+0.2% ± 0.08%)
sharding-w2 56.22 (-1.1% ± 0.5%) 52,677 (-2.8% ± 1.4%) 101,330 (+0.0% ± 0.07%) 72,774 (-0.3% ± 0.3%) 43,116 (+0.1% ± 0.1%) 1.395 (+0.3% ± 0.10%)
sharding-w8 148,442 (-0.1% ± 1.5%) 48.36 (+0.2% ± 1.0%) 58,648 (+0.2% ± 1.6%) 56,780 (+0.0% ± 0.07%) 64,176 (+0.3% ± 0.6%) 34,195 (+0.0% ± 0.2%) 0.1658 (-0.4% ± 2.5%)
Counters per txn
suite frontend stall l1i refill backend stall
pooler 72,742 (-9.0% ± 0.7%) 3,564 (-3.2% ± 0.1%)
lb 75,835 (-10.1% ± 0.8%) 3,684 (-3.6% ± 0.3%)
sharding-w2 153,843 (-4.6% ± 2.3%) 5,929 (-0.9% ± 0.9%)
sharding-w8 123,308 (-2.4% ± 1.1%) 4,790 (-0.6% ± 0.9%)
benchmark measure result baseline change bound
full_named_cached::aggregate instructions 146,308 144,637 +1.16% ± 0.00% +1%

Microbench: 461 of 462 measures within bounds.

Microbench latency: 4 benches changed more than 3%
benchmark latency baseline change instructions change
simple_cold::set 2,462 ns 2,586 ns -4.78% ± 2.18% +0.00% ± 0.00%
simple_cold::begin 1,948 ns 2,032 ns -4.13% ± 1.53% +0.00% ± 0.00%
simple_cold::update_by_key 4,314 ns 4,473 ns -3.54% ± 2.04% +0.00% ± 0.00%
simple_cold::update_all_shards 3,452 ns 3,565 ns -3.16% ± 1.26% +0.00% ± 0.00%
Hot code per txn
path base head change
pooler 103.6 KB 104.3 KB +0.7 KB
sharding-w2 158.4 KB 157.8 KB -0.6 KB

pooler:

crate base head change
pgdog::frontend::client::query_engine 19.8 KB 20.0 KB +0.2 KB
tokio 17.6 KB 17.8 KB +0.2 KB
pgdog::backend::pool 16.7 KB 16.6 KB -0.1 KB
pgdog::frontend (other) 8.9 KB 8.9 KB -0.1 KB
aws-lc (TLS crypto) 7.2 KB 7.4 KB +0.1 KB
rustls (TLS) 7.7 KB 7.2 KB -0.5 KB
pgdog::backend::server 6.0 KB 6.6 KB +0.6 KB
other 5.9 KB 5.6 KB -0.4 KB
everything else 13.8 KB 14.3 KB +0.5 KB
function head change
pgdog::frontend::client::Client::run::{{closure}} 6.7 KB -0.1 KB
pgdog::frontend::client::query_engine::query::<impl pgdog::frontend::client::query_engine: 6.0 KB +0.2 KB
pgdog::frontend::client::query_engine::QueryEngine::handle::{{closure}} 4.7 KB +0.1 KB
tokio::runtime::task::raw::poll 3.6 KB +0.1 KB
pgdog::frontend::client::query_engine::query::<impl pgdog::frontend::client::query_engine: 3.0 KB -0.1 KB

sharding-w2:

crate base head change
pgdog::frontend::router 26.8 KB 26.6 KB -0.1 KB
pgdog::frontend::client::query_engine 22.2 KB 21.8 KB -0.4 KB
tokio 17.8 KB 17.8 KB +0.1 KB
pgdog::backend::pool 17.6 KB 17.3 KB -0.3 KB
aws-lc (TLS crypto) 10.5 KB 10.4 KB -0.1 KB
pgdog::frontend (other) 10.0 KB 10.1 KB +0.1 KB
other 10.1 KB 9.9 KB -0.2 KB
rustls (TLS) 7.7 KB 7.4 KB -0.2 KB
everything else 35.8 KB 36.3 KB +0.6 KB
function head change
pgdog::frontend::client::Client::run::{{closure}} 7.6 KB +0.1 KB
pgdog::frontend::client::query_engine::query::<impl pgdog::frontend::client::query_engine: 5.9 KB +0.1 KB
pgdog::frontend::client::query_engine::QueryEngine::handle::{{closure}} 4.8 KB -0.2 KB
pgdog::frontend::router::parser::query::select::<impl pgdog::frontend::router::parser::que 3.9 KB +0.0 KB
tokio::runtime::task::raw::poll 3.7 KB -0.1 KB
lb flamegraph vs df1af3b

lb

Open interactive for hover, zoom and search.

lb removed

Open interactive.

microbench flamegraph vs df1af3b

microbench

Open interactive for hover, zoom and search.

microbench removed

Open interactive.

pooler flamegraph vs df1af3b

pooler

Open interactive for hover, zoom and search.

pooler removed

Open interactive.

sharding-w2 flamegraph vs df1af3b

sharding-w2

Open interactive for hover, zoom and search.

sharding-w2 removed

Open interactive.

sharding-w8 flamegraph vs df1af3b

sharding-w8

Open interactive for hover, zoom and search.

sharding-w8 removed

Open interactive.

Logs

lb, microbench, pooler, sharding-w2, sharding-w8, verdict.json

Compared 6109875 with df1af3b on c7a.metal-48xl (spot).

@jkaczman
jkaczman force-pushed the jk-subqueries-repl-values-w-unnest branch 4 times, most recently from a7a706c to 422f97c Compare November 9, 2026 22:01
@codecov

codecov Bot commented Nov 9, 2026 •

Copy link
Copy Markdown

@jkaczman
jkaczman force-pushed the jk-subqueries-repl-values-w-unnest branch from 6109875 to 5728343 Compare November 9, 2026 23:50
@jkaczman
jkaczman force-pushed the jk-subqueries-repl-values-w-unnest branch from 5728343 to f3aac4a Compare November 9, 2026 23:52

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant