Hi hackers, This is v4 of the patch adding a stats_last_updated column to pg_stat_statements.
The thread is somehow shifted to things that are not related to the patch initial idea. I decided to return to the beginning. I simplified the implementation to use GetCurrentTimestamp() directly instead of calculating the timestamp from GetCurrentStatementStartTimestamp() + total_time. The previous optimization was premature, benchmark testing proves GetCurrentTimestamp() adds no measurable overhead. Test environment: Dockerized Linux x86_64 under Windows host (the worst possible combination), PostgreSQL 19devel, gcc-14.2.0 Test: 1,000,000 iterations of PERFORM 1 (fastest possible statement) Unpatched PostgreSQL: track='none' (baseline): 562.07ms average track='all' (tracking): 719.17ms average Overhead: 157.10ms (27.9%) Patched PostgreSQL (with stats_last_updated): track='none' (baseline): 548.95ms average track='all' (tracking): 732.50ms average Overhead: 183.55ms (33.4%) Direct comparison (what matters): Unpatched track='all': 719.17ms Patched track='all': 732.50ms Difference: +13.33ms (+1.85%) Per-statement: 13.33ms / 1,000,000 = 13 nanoseconds The baseline comparison shows patched is actually faster (-13ms), which is impossible. This confirms the 13ms variance is a measurement noise, not real overhead. Real-world impact for 100ms query is 0.000013% overhead GetCurrentTimestamp() is the standard approach used throughout PostgreSQL for monitoring features. The measured overhead of 13 nanoseconds per statement is negligible for any realistic workload and well within measurement noise. The implementation captures GetCurrentTimestamp() before acquiring the spinlock, so no syscall occurs while holding the lock. This is simple, correct, and has no measurable performance impact. Changes from v2-v3: - Simplified implementation to use GetCurrentTimestamp() directly - Removed complex calculation with GetCurrentStatementStartTimestamp() and total_time computation (premature optimization) - Added comprehensive benchmark testing (unpatched vs patched) - Benchmark testing shows no measurable overhead (<2% in synthetic tests) - Measured overhead: 13ns per statement (1.85% for 1M iteration test, negligible for real queries >0.1ms) Changes from v1: - Rename column from last_executed to stats_last_updated (Christoph Berg) - Move timestamp from Counters struct to pgssEntry for better semantics - Place column at end of view to match stats_since naming convention - Fixed whitespace errors - Moved tests to entry_timestamp.sql (Sami Imseih) - Updated PGSS_FILE_HEADER to handle structure change Patch, benchmark script and raw results are attached. Best regards, Pavlo Golub
UNPATCHED PostgreSQL Test 1: track='none' (clean baseline, no pg_stat_statements overhead) - Run 1: 575.843 ms - Run 2: 554.241 ms - Run 3: 556.117 ms Average: 562.07 ms Test 2: track='all' (with pg_stat_statements tracking) - Run 1: 725.412 ms - Run 2: 713.809 ms - Run 3: 718.276 ms Average: 719.17 ms --- PATCHED PostgreSQL (with stats_last_updated column) Test 1: track='none' (clean baseline, no pg_stat_statements overhead) - Run 1: 540.163 ms - Run 2: 568.065 ms - Run 3: 538.595 ms Average: 548.95 ms Test 2: track='all' (with pg_stat_statements + stats_last_updated) - Run 1: 737.379 ms - Run 2: 725.067 ms - Run 3: 735.044 ms Average: 732.50 ms
v4-0001-pg_stat_statements-Add-stats_last_updated-column.patch
Description: Binary data
benchmark.sql
Description: Binary data
