fix: partition messages_lookup to stop the index bloat - #4106
Conversation
|
This PR may contain changes to database schema of one of the drivers. If you are introducing any changes to the schema, make sure the upgrade from the latest release to this change passes without any errors/issues. Please make sure the label |
|
You can find the images built from this PR at Built from 7a09731 |
1d46a0f to
19e87ac
Compare
Review round on #4106: - create+backfill now run atomically inside the advisory-lock DO block, so an interruption cannot leave a permanently empty lookup partition - reconciliation runs every factory iteration (newest-first) instead of once pre-loop: it no longer gates the 10s startup partition wait, the current hour heals first, and gaps opened by old-binary writers on a shared database self-repair within one iteration - stray lookup partitions with no messages sibling are dropped, closing the boot fatal-loop from range overlaps - notes: lock trade-off comments, v8 comment covers the timestamp index, getPartitionsList parameterized, test db url deduplicated
There was a problem hiding this comment.
The comment still refers to deleting rows
|
Some possible risks identified by Claude:
|
…ng backfill transaction
0c00f6f to
2ce560f
Compare
|
Hi @stubbsta,
true, it still row-deletes. Here's why we're leaving it for now: Retention policies stack (our fleets run size:50GB;time:32d together), and no deployment we know adds capacity: to the stack, it's a legacy mode from before time/size existed. It also can't be converted the way the others were: time and size are promises whole hourly partitions can keep, but "exactly the newest N rows" needs row-level deletes by definition — converting it would change what the setting means. So for this PR: the gap is documented directly on the function, need to create Issue first before deprecate it.
Yes, accepted trade-off, and in practice the window is small: the rebuild reads only the live rows from messages (~137k / ~38 MB after the fleet reindex), so it completes in seconds.
Yes, it's very cheap. Thanks for review. |
Problem
Store nodes have two tables. The big one (
messages) is cleaned by dropping hourly partitions — instant and clean. The small helper table (messages_lookup) is cleaned by deleting rows every 30 minutes. In Postgres, deleted rows leave dead space in indexes that is never given back. After months of this, ~20 MB of real data was buried under up to 1.3 GB of dead index per node — and while each cleanup pass waded through that dead space, the whole database briefly stalled, so any query running at that moment took >1s, evenSELECT version();. That is the slowQuery alert storm in #3790.Fix
Make
messages_lookuppartitioned, exactly likemessages:Tests: three new ones (partition lockstep; rebuild path; stray cleanup), plus the full archive suite — 155/155 against real Postgres 15.
Upgrade note
Right after the migration, hash-based store queries may briefly return empty while
messages_lookupis rebuilt from stored messages (newest first; seconds on current fleet data).What this PR does NOT fix (known, tracked separately)
capacity:Nretention still row-deletes — an exact row-count promise cannot be expressed as partition drops. Documented in code; unused by our fleets; convert-or-deprecate tracked in chore(archive): deprecate capacity retention policy #4123.close #3790