fix: Pruning window - #2438
Conversation
c0507dd to
6982012
Compare
|
|
||
| -- accounts --------------------------------------------------------------------------------------- | ||
|
|
||
| ALTER TABLE accounts ADD COLUMN valid_until BIGINT NOT NULL DEFAULT 9223372036854775807; |
There was a problem hiding this comment.
Are we sure we don't want this to be null instead? The magic number is a bit difficult to reference in sql.
There was a problem hiding this comment.
I second this. At least for me having NULL in valid_until if the entry is latest would look better.
| UPDATE accounts SET valid_until = next_versions.next_block_num | ||
| FROM ( | ||
| SELECT account_id, block_num, | ||
| LEAD(block_num) OVER (PARTITION BY account_id ORDER BY block_num) AS next_block_num | ||
| FROM accounts | ||
| ) AS next_versions |
There was a problem hiding this comment.
TIL about LEAD. I've always done this in a more roundabout fashion.
| /// Builds a version-3 database with versioned `is_latest` rows and verifies that migration 4 | ||
| /// backfills each row's `valid_until` with its successor's `block_num` (or the open sentinel). | ||
| #[test] | ||
| fn validity_interval_migration_backfills_from_versioned_rows() -> Result<()> { |
There was a problem hiding this comment.
Rather move this test to the actual migration itself.
There was a problem hiding this comment.
Do you mean as part of the sql or as part of the rs file that runs the migration?
kkovaacs
left a comment
There was a problem hiding this comment.
Apart from the i64::MAX -> NULL suggestion this looks good to me!
|
|
||
| -- accounts --------------------------------------------------------------------------------------- | ||
|
|
||
| ALTER TABLE accounts ADD COLUMN valid_until BIGINT NOT NULL DEFAULT 9223372036854775807; |
There was a problem hiding this comment.
I second this. At least for me having NULL in valid_until if the entry is latest would look better.
6982012 to
f1d38cf
Compare
Summary
Closes #2437.
History pruning deleted rows purely by age, but a row written before the cutoff can still be a key's applicable value for blocks inside the retention window, so historical vault, storage-map, and code reconstruction silently returned incomplete state.
Fix: explicit validity intervals
This PR replaces the
is_latestflag with the fact pruning actually needs: each row ofaccounts,account_vault_assets, andaccount_storage_map_valuesnow carries a validity interval[block_num, valid_until).valid_untilto the new row'sblock_num. Current rows are open-ended.i64::MAXrather than NULL, keeping every validity predicate a single range comparison that partial indexes can serve.004_validity_intervals.sqlbackfills existing rows in oneUPDATE … FROM+LEAD()window pass per table, dropsis_latest, and rebuilds the affected indexes.Effects
valid_until <= cutoff), i.e. iff it can no longer serve any block inside the retention window. Baseline rows survive by construction. Account codes reduce to one predicate: a code lives iff some row withvalid_until > cutoffreferences it — which covers in-window rows, current rows, and baselines in a single range scan.valid_until). The codes prune is an index-only scan of the coveringidx_accounts_code_validity. Verified viaEXPLAIN QUERY PLAN.select_account_vault_at_blockcollapses from a MAX-per-key self-join to interval membership (block_num <= X AND valid_until > X). All latest-row lookups keep their previous query plans (verified plan-identical between schema v3 and v4).Tests
validity_interval_migration_backfills_from_versioned_rows).test_prune_history(these fail against the old pruning predicate).Operator note
This bumps the store schema to version 4; existing databases must run the explicit migrate command before start (
verify_latest_schemarejects un-migrated databases). The backfill is a single pass per table and runs inside the migration transaction.Changelog