Skip to content

pgcolumnar.enable_metadata_count is an orphaned GUC, and count(*) loses to a parallel scan by default #133

Description

@jdatcmd

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions