Document five settings and correct two false claims (1.0-alpha docs pass) - #371
Conversation
Part of the 1.0-alpha docs accuracy pass (commandprompt#367). Every registered GUC is now in docs/configuration.md. Five were not: enable_ungrouped_vector_agg, enable_parallel_vector_agg, enable_column_projection and enable_index_fetch_penalty are user-facing and are documented as such; bulk_parallel_writer is internal, is marked GUC_NOT_IN_SAMPLE, and is recorded in its own section because it appears in pg_settings and a reader who finds it there deserves an answer. Two claims in limitations.md are wrong and are corrected: ANALYZE does not sample through the fetch-by-row-number path. It reads with a reader restricted to one row group. Measured with an instrumented build: zero calls into columnar_fetch_row during ANALYZE, against two for a control point query on the same table (commandprompt#359). Fetch cost does increase with the width of the table, where the document said it no longer does. An index fetch decodes the attribute prefix up to the highest column the query reads, not the columns it reads (commandprompt#363), and columns that exceed the fetch cache size limit are decoded again per fetch (commandprompt#359, commandprompt#364). Measured on ten text columns, same rows and same plan: 975 ms on the first column against 194,798 ms on the tenth. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
jdatcmd
left a comment
There was a problem hiding this comment.
Approved
Docs-only, CI green (which runs docs_style over docs/*.md in full), and it
fixes the two things that actually mattered for an alpha.
The limitations.md correction is the important half. The old text said a fetch
"decodes only the columns that the executor asks for", which #363 disproves: it
decodes the prefix up to the highest-numbered column referenced. That sentence was
not vague, it was wrong, and it was the sentence a user would have relied on when
laying out a wide table. Replacing it with both causes and the 975 ms / 194,798 ms
measurement is the right level of specificity.
Documenting enable_column_projection and enable_index_fetch_penalty closes a
real gap, since both are on by default. #372 covers the same two in the changelog,
so a reader arriving from either direction now finds them.
The bulk_parallel_writer entry is a good call. A GUC_NOT_IN_SAMPLE setting still
shows up in pg_settings, and "leave it alone" plus the reason it is safe to touch
is more useful than omitting it and letting someone guess.
One trivial note, not worth a round trip: the enable_index_fetch_penalty row says
"restore the pre-1.0-alpha planner behaviour" while VERSION still reads 1.0-dev
and nothing is cut yet. It reads fine once the alpha lands, which it will before
this text is user-visible. I will make sure the version cut does not contradict it.
Merging.
What
The docs accuracy pass from #367. Two separate problems: settings that exist and are
not documented, and documented claims that are not true.
Every registered GUC is now documented
Five were missing from
docs/configuration.md. Four are user-facing and land inScan and execution:
pgcolumnar.enable_ungrouped_vector_aggpgcolumnar.enable_parallel_vector_aggpgcolumnar.enable_column_projectionpgcolumnar.enable_index_fetch_penaltyThe fifth,
pgcolumnar.bulk_parallel_writer, is internal — set bypgcolumnar.parallel_copyworkers and markedGUC_NOT_IN_SAMPLE. It gets its ownshort Internal settings section rather than a row among the tuning knobs, because
it appears in
pg_settingsand a reader who finds it there deserves an answer ratherthan silence.
Checked mechanically rather than by eye:
Two claims in limitations.md are wrong
"
ANALYZEsamples the rows through the fetch path and not by block." It does not.columnar_scan_analyze_next_tuplereads with a reader restricted to one row group.Measured with an instrumented build (an
elogat the top ofcolumnar_fetch_row,PG18 assert, statement-marked log):
The control is an indexed point query on the same table, so the probe is live and the
zero is real. The sentence is replaced with what is true and still explains the cost:
the sampler offers every row of every block it visits, so the cost follows rows
offered rather than rows kept.
"The cost therefore no longer increases with the width of the table." It does, in
two ways that are easy to meet at once, and this is the sharp edge jdatcmd asked to
have documented rather than left silent (#367):
query reads, not the columns it reads (The index-fetch cost model sizes the decode from the emitted columns, but the fetch decodes the attribute prefix: 200x invisible to reltarget->width #363);
(The fetch cache cliff persists after #357: 4 to 5 aggregate columns is a 47x jump #359, and the bound correction in #361's fetch cache is not bounded by 4x the cap: one entry measures 62 MB against 32 MB on a wide varlena table, and gets 1.14x #364).
Measured on ten
textcolumns, same rows and same plan: 975 ms on the firstcolumn against 194,798 ms on the tenth.
Note this is documented as current behaviour. #368 fixes the cost model so the
planner stops walking into it, which is a different thing from the fetch itself
becoming cheap — the fetch still decodes the prefix.
Style
test/ste_check.pypasses on every user-facing document, which is whatdocs_style.shgates on. The measured sentences needed splitting to stay inside the25-word STE limit; that is a real constraint on how these paragraphs read and I have
kept the numbers rather than the prose where they conflicted.
🤖 Generated with Claude Code