-- The rewrite of every segment decides again what a build decides from the data (key_cut, the order arrays, the point directories of the options the build chose), -- so an index built on a table in the order of its tenants and rewritten after rows of every tenant were appended is as small as a rebuild of it --: the maintained size is within 5% of the REINDEX of the same rows, the answers are the table's, and the choice is the build's. CREATE EXTENSION pg_sift; SET sift.test_col_net = off; -- this test is of the dirty units and their rewrite (col_net_agg is of the sidecar VACUUM writes for them) SET client_min_messages = warning; SET max_parallel_workers_per_gather = 0; SET max_parallel_maintenance_workers = 0; SET sift.col_auto_merge = off; SET sift.async_maintenance = off; -- no worker takes the steps below (col_key_cut_redecide_async is the same rewrite with it on) SET sift.col_wbuf_ref = off; -- a buffer of references holds more rows at its limit, so VACUUM promotes it whole and leaves the second index nothing to rewrite (col_wbuf_arena* test the references) CREATE TABLE rc (id int PRIMARY KEY, tenant_id int, foreign_id int, counter_a int, updated_at timestamp, pad text); INSERT INTO rc SELECT i, i / 150, 1 + i % 12, hashint4(i) & 1048575, TIMESTAMP '2026-01-01' + (hashint4(i + 7) & 16777215) * INTERVAL '1 second', repeat('x', 100) FROM generate_series(1, 120000) i; VACUUM ANALYZE rc; CREATE INDEX rc_ix ON rc USING sift_col (id, tenant_id, foreign_id, counter_a, updated_at) WITH (dead_rewrite_pct = 50); -- the same columns with the key the user wrote CREATE INDEX rc_off ON rc USING sift_col (id, tenant_id, foreign_id, counter_a, updated_at) WITH (key_cut = 'off'); -- built on rows in the order of the tenants: no cut SELECT reloptions::text ~ 'key_cut' AS cut_at_build FROM pg_class WHERE relname = 'rc_ix'; -- rows of every tenant appended at the end of the heap, a tenth of the rows deleted INSERT INTO rc SELECT i, (hashint4(i) & 2147483647) % 800, 1 + i % 12, hashint4(i) & 1048575, TIMESTAMP '2026-01-01' + (hashint4(i + 7) & 16777215) * INTERVAL '1 second', repeat('x', 100) FROM generate_series(120001, 240000) i; DELETE FROM rc WHERE id % 10 = 3; VACUUM ANALYZE rc; -- the NOTICE names the choice as the option holds it SET client_min_messages = notice; \set VERBOSITY terse SELECT sift.col_maintain('rc_ix'); \set VERBOSITY default SET client_min_messages = warning; SELECT sift.col_maintain('rc_off'); VACUUM rc; VACUUM rc; SELECT pg_relation_size('rc_ix') AS maintained \gset SELECT reloptions::text ~ 'key_cut=auto: foreign_id' AS cut_after_rewrite FROM pg_class WHERE relname = 'rc_ix'; SELECT sift.col_verify('rc_ix'); -- an option the user wrote is not changed by the rewrite SELECT reloptions::text ~ 'key_cut=off' AND reloptions::text !~ 'key_cut=auto' AS user_option_kept FROM pg_class WHERE relname = 'rc_off'; DROP INDEX rc_off; -- the answers are the table's SELECT count(*) AS n, sum(counter_a) AS s, count(DISTINCT tenant_id) AS t FROM rc WHERE foreign_id = 5 \gset maint_ SET sift.enable_agg = off; SELECT count(*) = :maint_n AND sum(counter_a) = :maint_s AND count(DISTINCT tenant_id) = :maint_t AS same_answers FROM rc WHERE foreign_id = 5; RESET sift.enable_agg; REINDEX INDEX rc_ix; SELECT pg_relation_size('rc_ix') AS rebuilt \gset SELECT :maintained <= :rebuilt * 1.05 AS maintained_within_5_percent; DROP TABLE rc; DROP EXTENSION pg_sift;