Repository navigation
get_pg_server_config, get_pg_logging_audit and the PostgreSQL config panel plan a day's chunks, not every retained pg_server_config chunk (#3974) - #3992
Merged
Conversation
…panel plan a day's chunks, not every retained pg_server_config chunk (#3974) The three tool-side reads of the newest pg_server_config snapshot (CurrentConfigSql, OverrideSql, NewestSnapshotSql) had no lower bound on the MAX(collection_time) anchor or the row scan, so TimescaleDB planned every retained chunk before reading a row: 4.0-8.3s cold on a 366-chunk rig. Bounds CurrentConfigSql and NewestSnapshotSql the way #3928 bounded the analysis reads: a day's lower bound on both the anchor and the outer scan, falling back to unbounded only when the day found nothing. OverrideSql needed a different shape (the design question the issue raised): most servers have zero overrides, so a naive "retry when no rows" loop would fall back on nearly every call. Its anchor now rides its own column through a LEFT JOIN, so the retry loop can tell "no snapshot in the day" from "a snapshot with zero overrides" and only retries the former. Measured on the rig: the bounded read plans in ~3ms against 21-288ms unbounded on 366 one-day chunks. Answers are unchanged: a dark target's fallback still finds its newest snapshot however old. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GdmA4ND1wLSqA91ax1m4xv
erikdarlingdata
enabled auto-merge (squash)
September 23, 2026 05:32
erikdarlingdata
added a commit
that referenced
this pull request
Sep 23, 2026
…ntries in their sections (#4080) Adds 42 entries and 42 link refs (#3992, #3995, #3996, #3998, #4001, #4002, #4003, #4007, #4010, #4011, #4013, #4015, #4020, #4022, #4025, #4029, #4030, #4031, #4036, #4038, #4039, #4040, #4044, #4047, #4048, #4049, #4050, #4051, #4055, #4061, #4063, #4064, #4065, #4066, #4067, #4068, #4069, #4070, #4071, #4073, #4074, #4078). Each PR's entry was buffered, and this lands every entry whose PR was merged on origin/dev when it ran. #3989 left 26 entries under bare 'Changed' and 'Fixed' lines above '### Added'. They move into '### Changed' and '### Fixed', below the new entries, and one blank line stays under [Unreleased]. Claude-Session: https://claude.ai/code/session_01Ua31ugERL5DmhFVRtf6keQ Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3974.
Why
DarlingPgServerConfigReader.CurrentConfigSqlandOverrideSql(get_pg_server_config, and the WPFviewer's PostgreSQL config panel) and
DarlingPgLoggingAuditReader.NewestSnapshotSql(
get_pg_logging_audit) had no lower bound on the newest-snapshot anchor or the row scan.pg_server_configkeeps 365 days of hourly snapshots in one-day chunks, so TimescaleDB had to plan every retained chunk before
reading a row on every call.
What changes
CurrentConfigSqlandNewestSnapshotSqlget the PostgreSQL-target config reads plan every retained pg_server_config chunk: seconds per read once a store holds a year of snapshots #3928 shape exactly: a day's lower bound on both theanchor's
MAX(collection_time)and the outer row scan, with a fallback to unbounded only when the dayfound nothing (
DarlingPgServerConfigReader.ConfigSnapshotLowerBounds, shared by both readers).OverrideSqlneeded a different shape - the design question the issue raised. Most servers have zeroper-database/per-role overrides, so retrying on "the read returned no rows" would run the unbounded
fallback on nearly every call, defeating the fix. Instead the anchor is a one-row CTE LEFT JOINed to the
override rows, so its
collection_timerides on every call even with zero overrides; the retry loop keyson that column, never on row count.
newest snapshot however old, through the same fallback rung these reads always had.
Test plan
PgServerConfigToolBoundTests(new): pins the bound on all three statements, the day-first/fallbackloop at each call site (keyed on row count for two, on the anchor column for
OverrideSql), and thebounds themselves.
PgServerConfigTests.TheCurrentReadAnchorsOnTheNewestSnapshot_NeverComingUpEmptyForADarkServerupdated: the old pin asserted "no
collection_time >=anywhere"; the property that matters (a darktarget never comes up empty) still holds, now through a bound-plus-guaranteed-fallback rather than no
bound at all.
PgServerConfigOverrideLivePostgresTests(existing, gated): its hand-builtCurrentConfigSqlcallupdated for the new
$4parameter; still green.PgServerConfigToolBoundLiveTests(new, gatedDARLING_TEST_PG): seeds 11 daily chunks and EXPLAINsall three reads with each bound - the day plans 1-4 chunk scans, the fallback plans all 11; a dark
target (72h) still answers with its newest snapshot on all three reads; a snapshot with zero overrides
does not fall back and leak an older snapshot's overrides (the case the design question was about).
21-288 ms (812-12,592 buffers) against ~2.9-3.0 ms bounded (812 buffers) with a literal-equivalent
bound - the same order of magnitude the issue measured (4.0-8.3s at full 365-day retention; this rig's
warm/cold variance was noisier than the issue's but the bounded shape was consistently ~7x+ cheaper at
every measurement).
Darling.TestsPgServerConfig/PgLoggingAudit classes, 64 total, 0 failed (7 skipped - ungatedlive tests).
Darling.Tests, 12,934 total, 0 failed (1 pre-existing flake inTimescaleSupportTests.EndToEnd_RetentionPoliciesActuallyApply_AndAreCreatedPaused_AgainstDevPostgres,confirmed passing alone, unrelated to this change - not touched by this PR).
Lite and the Dashboard do not monitor PostgreSQL, so there is no parity item.
🤖 Generated with Claude Code
https://claude.ai/code/session_01GdmA4ND1wLSqA91ax1m4xv