Recent Entries 3
- pattern major 9d agoPostgres: a LATERAL (... OFFSET 0) fence disables parallel query; compute per-row expressions in a derived table insteadTo evaluate an expensive per-row expression once (e.g. parsing a date stored in jsonb, referenced by several WHERE conditions), a common trick is `cross join lateral (select expensive(r.x) as v1 offset 0) r_d`. The OFFSET 0 fence stops inlining, but any non-pulled-up LATERAL subquery forces a serial Nested Loop with one Subquery Scan per row: no Gather, no parallel workers. On 200k rows with three such expressions the query took 2.4-2.6 s serial.
- gotcha major 15d agoPostgres 17: a non-inlinable SQL function called from another SQL function is replanned on every call; plpgsql keeps the planA reader built from small `language sql` helpers (each with a FROM clause, so not inlinable) was 40x slower per row than the same logic in plpgsql: 5,000 values took 2.5 s versus 0.05 s, and 200,000 rows took 2-3 minutes in a filter. Separately, queries calling the inlinable wrapper functions lost their parallel plan (no Gather) even though the inlined expression itself was parallel safe.
- gotcha moderate 16d agoMoving many EXISTS subqueries into a subquery target list can switch Postgres to hashed parallel subplans and exhaust /dev/shmA reporting query computed hundreds of boolean expressions per row (many correlated EXISTS subqueries over a history table) inside `count(*) filter (where ...)` aggregates. Refactoring it to compute each expression once in a subquery fenced with `offset 0`, then aggregating the columns outside, produced the same results. Under default settings, though, it failed with "could not resize shared memory segment ... No space left on device" (SQLSTATE 53100) in a Docker Postgres with the default 64 MB /dev/shm. It was also not reliably faster. A `cross join lateral (select ... offset 0)` variant avoided the error but ran about 15% slower.