Add pg_stat_statements_nsp extension for DSM-based query statistics#14
Add pg_stat_statements_nsp extension for DSM-based query statistics#14
Conversation
This extension demonstrates how to track query execution statistics without requiring the extension to be loaded via shared_preload_libraries. Key features: - Uses DSM Registry (PostgreSQL 15+) for lazy allocation of shared memory - Can be loaded via LOAD command, session_preload_libraries, or shared_preload_libraries - Shares statistics across all sessions via dshash Limitations compared to pg_stat_statements: - Statistics don't survive server restart (no persistence to disk) - Simplified statistics (no planning stats, WAL stats, etc.) - No configurable max entries (uses fixed size) This serves as a proof-of-concept for extensions that need shared state but want to avoid the operational complexity of shared_preload_libraries. https://claude.ai/code/session_01MgkmQMtkSQMPuQ2zPutDjW
- Add missing queryjumble.h include for EnableQueryId() declaration - Initialize queryid variable to avoid uninitialized warning - Update expected test output to match actual psql formatting https://claude.ai/code/session_01MgkmQMtkSQMPuQ2zPutDjW
Ignore regression test output files that should not be committed. https://claude.ai/code/session_01MgkmQMtkSQMPuQ2zPutDjW
Test Results for
|
| Check | Result |
|---|---|
| Compilation | PASS - Clean build, zero warnings |
Regression test (make installcheck) |
PASS - 1/1 tests passed |
| Manual: basic query tracking | PASS - SELECT, INSERT, UPDATE, DELETE all tracked |
| Manual: call count accumulation | PASS - SELECT 1 x5 shows calls=5 correctly |
Manual: compute_query_id=off |
PASS - Silently skips tracking (0 entries) |
| Manual: error handling | PASS - Stats survive division-by-zero error, continue working |
| Manual: cross-session visibility | PASS - Stats visible from sessions that didn't LOAD |
Code Review Issues Found
High Severity:
-
exec_nested_levelcorruption on error (pg_stat_statements_nsp.c:196-212) — Ifstandard_ExecutorStartthrows,exec_nested_levelis incremented but never decremented (noPG_TRY/PG_FINALLY). This permanently breaks tracking for the rest of the session. The realpg_stat_statementsavoids this by not using a nesting counter in ExecutorStart/ExecutorEnd at all. -
Unbounded hash table growth —
PGSS_NSP_MAX_ENTRIES(1000) is defined but never enforced. There's no eviction logic. In production with diverse workloads, DSA memory grows without limit. The realpg_stat_statementshasentry_dealloc()eviction. -
Missing
REVOKE ALLon reset function (pg_stat_statements_nsp--1.0.sql) — Any database user can callpg_stat_statements_nsp_reset()and wipe all stats for all users. The realpg_stat_statementsdoesREVOKE ALL ON FUNCTION ... FROM PUBLIC.
Medium Severity:
-
Uses
es_processedinstead ofes_total_processed(line 243) — Undercounts rows for multi-batch/cursor queries. The realpg_stat_statementsusesqueryDesc->estate->es_total_processed. -
Static timing variables can leak across queries — If
ExecutorEndis skipped on error,query_timing_activestays true and contaminates the next query's timing. The realpg_stat_statementsuses per-queryqueryDesc->totaltimeallocated in the query memory context. -
UINT64CONST(0)vsINT64CONST(0)type mismatch —queryIdisint64(signed) but compared against unsigned constant. Functionally harmless for zero, but inconsistent with upstream style.
Low Severity:
- Missing
meson.buildfor in-tree builds with the Meson build system. - Unnecessary spinlocks (dshash partition LWLock already serializes access).
- Minimal test coverage (no concurrent access tests, no error path tests,
LIMIT 5makes test order-dependent).
REV Code Review Report
BLOCKING ISSUES (2)HIGH
MEDIUM
NON-BLOCKING (6)MEDIUM
MEDIUM
MEDIUM
MEDIUM
LOW
INFO Missing POTENTIAL ISSUES (3)MEDIUM
LOW
LOW
TEST COVERAGE GAPSThe test suite is a basic smoke test. Key missing scenarios:
Summary
All blocking and non-blocking issues have been fixed in the local branch REV-assisted review (AI analysis by postgres-ai/rev) |
REV Code Review Report — Round 2 (post-fixes)
BLOCKING ISSUES (0)No blocking issues found. All previous blocking issues have been resolved. NON-BLOCKING (4)MEDIUM
MEDIUM
MEDIUM
LOW
POTENTIAL ISSUES (2)LOW
LOW
TEST COVERAGE GAPS (top items)
GUIDELINES (INFO)
DOCS GAPS
Summary
Improvement from Round 1: All 8 blocking/non-blocking issues from Round 1 are resolved. Remaining issues are defense-in-depth hardening, test coverage, and documentation. REV-assisted review (AI analysis by postgres-ai/rev) |
Documents the new pg_stat_statements_nsp extension which demonstrates how to use the DSM Registry to create query statistics tracking without requiring shared_preload_libraries. Key points documented: - How to install and use the extension - Comparison with full pg_stat_statements - Technical implementation details using DSM Registry - Limitations (no persistence, fixed size, no query text) https://claude.ai/code/session_01MgkmQMtkSQMPuQ2zPutDjW
Enable pg_stat_statements to work without shared_preload_libraries by using the DSM Registry for dynamic shared memory allocation when loaded via LOAD or session_preload_libraries. Key changes: - Detect loading context in _PG_init() and set use_dsm_registry flag - Use GetNamedDSMSegment() and GetNamedDSHash() for shared state in DSM mode - Conditionally define PGC_POSTMASTER/PGC_SIGHUP GUCs only in preload mode - Add DSM-specific code paths in pgss_store(), pg_stat_statements_internal(), and entry_reset() using dshash_* functions instead of hash_* functions - Use dshash_seq_init/next/term for iterating entries in DSM mode - Use dshash_delete_entry/dshash_delete_current for entry removal in DSM mode - Skip query text storage and file operations in DSM mode Limitations in DSM mode: - Statistics do not persist across server restarts - Query text is not stored (shows NULL in the query column) - No automatic garbage collection or deallocation tracking - compute_query_id must be explicitly enabled https://claude.ai/code/session_01MgkmQMtkSQMPuQ2zPutDjW
Summary
This PR introduces a new PostgreSQL extension
pg_stat_statements_nspthat tracks SQL statement execution statistics without requiringshared_preload_libraries. The extension demonstrates the use of the DSM Registry (introduced in PostgreSQL 15) to create and manage shared data structures that can be lazily initialized when the extension is first loaded.Key Changes
New extension module:
contrib/pg_stat_statements_nsp/with complete implementationCore functionality:
pg_stat_statements_nsp()function returns query statistics as a set of recordspg_stat_statements_nsp_reset()function clears all accumulated statisticspg_stat_statements_nspview provides convenient access to statistics with computed mean_timepg_read_all_statsroleBuild infrastructure:
Notable Implementation Details
pg_stat_statements, this extension can be loaded viaLOADcommand,session_preload_libraries, orshared_preload_librariesGetNamedDSHash()to create or attach to a shared hash table, ensuring thread-safe initialization across multiple backendscompute_query_idGUC to be enabled (either viaEnableQueryId()during shared preload or manually set by user)instr_timeinfrastructure for accurate query timingLimitations
pg_stat_statements(no planning stats, WAL stats, etc.)https://claude.ai/code/session_01MgkmQMtkSQMPuQ2zPutDjW