Analysis: Adjusting pg_stat_get_lock() prorows to Match Actual Lock Type Count
Core Problem
This thread addresses a minor but legitimate planner-estimation inaccuracy in the system catalog function pg_stat_get_lock() (exposed via the pg_stat_lock view). The function is a set-returning function (SRF) that emits one row per lock type tracked by the statistics subsystem. Because it is an SRF written in C, the planner has no way to derive a row-count estimate from relation statistics; it relies entirely on the prorows field declared in pg_proc.dat.
The declared prorows = 10 is stale relative to the function's actual behavior, which returns 12 rows — one per defined lock type. The discrepancy is small in absolute terms, but for a function whose cardinality is deterministic and fixed at compile time, there is no reason for the estimate to be wrong at all.
Why This Matters Architecturally
-
Deterministic cardinality should be exact. Unlike SRFs whose output depends on runtime input (e.g.
generate_series(a,b)orunnest(arr)),pg_stat_get_lock()returns a compile-time-fixed number of rows equal to the number of lock-type enum entries. There is no statistical guesswork involved — the correctprorowsvalue is knowable. -
Downstream plan quality. While a 10-vs-12 delta is unlikely to flip a plan shape on its own,
pg_stat_lockis often joined against other catalogs or filtered in monitoring queries. When an SRF feeds a nested loop or hash join, an underestimate of 20% in the outer side can cascade — particularly once the view is wrapped in more complex monitoring SQL. Keeping catalog-functionprorowsin sync with reality is a standard hygiene item and has been adjusted for similar functions historically (e.g.pg_stat_get_backend_*,pg_get_keywords, etc.). -
Consistency invariant. The number of lock types is defined by an enum/array in the lock-stats infrastructure. Any patch that adds a lock type must bump
prorowsin lockstep, and the current mismatch suggests that invariant was silently violated at some point — either the set of lock types grew from 10 to 12 without the catalog metadata being updated, orprorowswas an initial guess that was never tightened.
Proposed Change
The patch is minimal and mechanical:
src/include/catalog/pg_proc.dat: changeprorows => '10'toprorows => '12'forpg_stat_get_lock.src/backend/utils/adt/pgstatfuncs.c(or thepgstat_lock.cthe author refers to): two small comment tweaks on helper functions, offered as optional cleanup.
Note that prorows only affects the planner; the executor still emits whatever the function actually produces. So the patch is semantically a pure optimizer hint adjustment with no runtime behavior change and no catalog-version bump requirement beyond the usual CATALOG_VERSION_NO bump for any pg_proc.dat edit.
Design Considerations / Tradeoffs
- Should
prorowsbe tied to a symbolic constant rather than a literal? Thepg_proc.datformat only accepts literals, so a hand-maintained value is unavoidable. A code comment near the lock-type enum reminding maintainers to updateprorowswould be more valuable than adjusting the number once — but this patch does not add such a comment. Reviewers may ask for that. - Future-proofing. If the lock-type list is expected to grow (e.g. new lock classes added for new subsystems), this patch will again be out of date. That argues for either (a) the enum-adjacent comment mentioned above, or (b) a regression test that compares
prorowsto the actual row count returned. - Comment tweaks bundled in. The author correctly flags that mixing unrelated doc changes with a functional fix is a review-friction concern and volunteers to drop them. Standard pgsql-hackers practice would be to either split into two patches or keep them bundled only if trivially related; the author's flexibility here is appropriate.
Participant Assessment
Only one message from the original poster (Evan Li) exists at the time of this analysis. This is a first-patch-style contribution — small, self-contained, with a reproducer via EXPLAIN ANALYZE and a clearly presented before/after. No committer has yet weighed in. The change is small enough that it is likely to be picked up by a committer with minimal review, possibly with a request to either drop the comment changes or justify them explicitly.
Likely Review Outcomes
- Patch accepted as-is with the
prorowsbump; comment tweaks kept if genuinely improving clarity, dropped otherwise. - Reviewer may request adding a
StaticAssertStmtor a comment adjacent to the lock-type definition reminding maintainers to keepprorowssynchronized. - Catalog version bump handled by the committer at commit time (customary — submitters are usually told not to include it).