Found by running the full benchmark suite against current main and comparing to the recorded bench/sample_output_pg17.txt.
What the benchmark showed
count(*) on the full table, 6,000,000 rows, PostgreSQL 17 non-assert:
|
median |
recorded in bench/sample_output_pg17.txt (3M rows, format 2.1) |
0.02 ms |
| current, default settings |
6.52 ms |
current, max_parallel_workers_per_gather = 0 |
~1.75 ms |
Scale doubled, so some increase is expected, but not from 0.02 ms to 6.52 ms.
Two separate things
1. The GUC is orphaned. columnar_enable_metadata_count is declared in columnar.h:159, defined in columnar_vector.c:74, and registered as pgcolumnar.enable_metadata_count in columnar_tableam.c:1193 with a description promising "Answer count(*) from catalog metadata without scanning". Nothing reads it. grep -rn 'columnar_enable_metadata_count' src/ returns only the declaration, the definition, and the registration.
git log -S says why: the last commit touching it is 881fa51 Phase H2: remove the 1.0-dev (2.2) on-disk format, catalog, and selector. The consumer went with the 2.2 path and the knob stayed behind. So the setting is user-visible, defaults to on, documents a behaviour, and does nothing.
count(*) is still answered without decoding column data: the vectorized aggregate path sums each row group's rowCount (columnar_vector.c:1008). So the capability survives; what was lost is the dedicated catalog-level shortcut and, with it, the meaning of the GUC.
2. The planner prefers a parallel scan. With parallelism at its default, EXPLAIN shows Gather over Partial Aggregate rather than the columnar path. Disabling parallelism gives Custom Scan (ColumnarScan) with Columnar Vectorized Aggregates: 1 and runs about 3.7x faster on the benchmark table. The near-constant-time path is losing on cost to a plan that reads the table.
Suggested resolution
Either wire the GUC back to something real or remove it, and either way make the costing reflect that the columnar aggregate path does not scan. A knob that does nothing is worse than no knob, and docs/features.md:48 currently promises the behaviour the knob names.
Not urgent for correctness: results are right either way. It is a performance and honesty issue.
Found by running the full benchmark suite against current
mainand comparing to the recordedbench/sample_output_pg17.txt.What the benchmark showed
count(*)on the full table, 6,000,000 rows, PostgreSQL 17 non-assert:bench/sample_output_pg17.txt(3M rows, format 2.1)max_parallel_workers_per_gather = 0Scale doubled, so some increase is expected, but not from 0.02 ms to 6.52 ms.
Two separate things
1. The GUC is orphaned.
columnar_enable_metadata_countis declared incolumnar.h:159, defined incolumnar_vector.c:74, and registered aspgcolumnar.enable_metadata_countincolumnar_tableam.c:1193with a description promising "Answer count(*) from catalog metadata without scanning". Nothing reads it.grep -rn 'columnar_enable_metadata_count' src/returns only the declaration, the definition, and the registration.git log -Ssays why: the last commit touching it is881fa51 Phase H2: remove the 1.0-dev (2.2) on-disk format, catalog, and selector. The consumer went with the 2.2 path and the knob stayed behind. So the setting is user-visible, defaults to on, documents a behaviour, and does nothing.count(*)is still answered without decoding column data: the vectorized aggregate path sums each row group'srowCount(columnar_vector.c:1008). So the capability survives; what was lost is the dedicated catalog-level shortcut and, with it, the meaning of the GUC.2. The planner prefers a parallel scan. With parallelism at its default,
EXPLAINshowsGatheroverPartial Aggregaterather than the columnar path. Disabling parallelism givesCustom Scan (ColumnarScan)withColumnar Vectorized Aggregates: 1and runs about 3.7x faster on the benchmark table. The near-constant-time path is losing on cost to a plan that reads the table.Suggested resolution
Either wire the GUC back to something real or remove it, and either way make the costing reflect that the columnar aggregate path does not scan. A knob that does nothing is worse than no knob, and
docs/features.md:48currently promises the behaviour the knob names.Not urgent for correctness: results are right either way. It is a performance and honesty issue.