Add PG18 support for VACUUM/ANALYZE with ONLY option on partitioned distributed tables

pull/8365/head
Mehmet Yilmaz 2025-12-05 08:59:44 +00:00
parent 990312bf61
commit 02af7f84fc
2 changed files with 220 additions and 26 deletions

View File

@ -1815,21 +1815,26 @@ SELECT create_distributed_table('vac_analyze_only', 'a');
(1 row)
INSERT INTO vac_analyze_only VALUES (1), (2), (3);
-- ANALYZE (no ONLY) should recurse into shard placements
ANALYZE vac_analyze_only;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part;
SELECT max(last_analyze) AS analyze_before_only
FROM pg_stat_all_tables
WHERE relname LIKE 'vac_analyze_only_%'
SELECT coalesce(max(last_analyze), 'epoch'::timestamptz) AS analyze_before_only
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part'
AND relname LIKE 'vac_analyze_only_%'
\gset
\c - - - :master_port
SET search_path TO pg18_vacuum_part;
-- ANALYZE ONLY should not recurse into shard placements
ANALYZE ONLY vac_analyze_only;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part;
SELECT max(last_analyze) = :'analyze_before_only' AS analyze_only_skipped
FROM pg_stat_all_tables
WHERE relname LIKE 'vac_analyze_only_%';
SELECT max(last_analyze) = :'analyze_before_only'::timestamptz
AS analyze_only_skipped
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part'
AND relname LIKE 'vac_analyze_only_%';
analyze_only_skipped
---------------------------------------------------------------------
t
@ -1837,21 +1842,26 @@ WHERE relname LIKE 'vac_analyze_only_%';
\c - - - :master_port
SET search_path TO pg18_vacuum_part;
-- VACUUM (no ONLY) should recurse into shard placements
VACUUM vac_analyze_only;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part;
SELECT max(last_vacuum) AS vacuum_before_only
FROM pg_stat_all_tables
WHERE relname LIKE 'vac_analyze_only_%'
SELECT coalesce(max(last_vacuum), 'epoch'::timestamptz) AS vacuum_before_only
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part'
AND relname LIKE 'vac_analyze_only_%'
\gset
\c - - - :master_port
SET search_path TO pg18_vacuum_part;
-- VACUUM ONLY should not recurse into shard placements
VACUUM ONLY vac_analyze_only;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part;
SELECT max(last_vacuum) = :'vacuum_before_only' AS vacuum_only_skipped
FROM pg_stat_all_tables
WHERE relname LIKE 'vac_analyze_only_%';
SELECT max(last_vacuum) = :'vacuum_before_only'::timestamptz
AS vacuum_only_skipped
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part'
AND relname LIKE 'vac_analyze_only_%';
vacuum_only_skipped
---------------------------------------------------------------------
t
@ -1862,7 +1872,86 @@ SET search_path TO pg18_vacuum_part;
DROP SCHEMA pg18_vacuum_part CASCADE;
NOTICE: drop cascades to table vac_analyze_only
SET search_path TO pg18_nn;
-- END PG18 Feature: VACUUM/ANALYZE recurse into inheritance children by default
-- END PG18 Feature: VACUUM/ANALYZE support ONLY to limit processing to the parent
-- PG18 Feature: VACUUM/ANALYZE ONLY on a partitioned distributed table
-- Ensure Citus does not recurse into shard placements when ONLY is used
-- on the partitioned parent.
-- PG18 commit: https://github.com/postgres/postgres/commit/62ddf7ee9
CREATE SCHEMA pg18_vacuum_part_dist;
SET search_path TO pg18_vacuum_part_dist;
SET citus.shard_count = 2;
SET citus.shard_replication_factor = 1;
CREATE TABLE part_dist (id int, v int) PARTITION BY RANGE (id);
CREATE TABLE part_dist_1 PARTITION OF part_dist FOR VALUES FROM (1) TO (100);
CREATE TABLE part_dist_2 PARTITION OF part_dist FOR VALUES FROM (100) TO (200);
SELECT create_distributed_table('part_dist', 'id');
create_distributed_table
---------------------------------------------------------------------
(1 row)
INSERT INTO part_dist
SELECT g, g FROM generate_series(1, 199) g;
-- ANALYZE (no ONLY) should recurse into partitions and shard placements
ANALYZE part_dist;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part_dist;
SELECT coalesce(max(last_analyze), 'epoch'::timestamptz) AS analyze_before_only
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part_dist'
AND relname LIKE 'part_dist_%'
\gset
\c - - - :master_port
SET search_path TO pg18_vacuum_part_dist;
-- ANALYZE ONLY should not recurse into shard placements
ANALYZE ONLY part_dist;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part_dist;
SELECT max(last_analyze) = :'analyze_before_only'::timestamptz
AS analyze_only_partitioned_skipped
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part_dist'
AND relname LIKE 'part_dist_%';
analyze_only_partitioned_skipped
---------------------------------------------------------------------
t
(1 row)
\c - - - :master_port
SET search_path TO pg18_vacuum_part_dist;
-- VACUUM (no ONLY) should recurse into partitions and shard placements
VACUUM part_dist;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part_dist;
SELECT coalesce(max(last_vacuum), 'epoch'::timestamptz) AS vacuum_before_only
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part_dist'
AND relname LIKE 'part_dist_%'
\gset
\c - - - :master_port
SET search_path TO pg18_vacuum_part_dist;
-- VACUUM ONLY parent: core warns and does no work; Citus must not
-- propagate to shard placements.
VACUUM ONLY part_dist;
WARNING: VACUUM ONLY of partitioned table "part_dist" has no effect
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part_dist;
SELECT max(last_vacuum) = :'vacuum_before_only'::timestamptz
AS vacuum_only_partitioned_skipped
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part_dist'
AND relname LIKE 'part_dist_%';
vacuum_only_partitioned_skipped
---------------------------------------------------------------------
t
(1 row)
\c - - - :master_port
SET search_path TO pg18_vacuum_part_dist;
DROP SCHEMA pg18_vacuum_part_dist CASCADE;
NOTICE: drop cascades to table part_dist
SET search_path TO pg18_nn;
-- END PG18 Feature: VACUUM/ANALYZE ONLY on partitioned distributed table
-- cleanup with minimum verbosity
SET client_min_messages TO ERROR;
RESET search_path;

View File

@ -1125,55 +1125,160 @@ ROLLBACK;
-- PG18 commit: https://github.com/postgres/postgres/commit/62ddf7ee9
CREATE SCHEMA pg18_vacuum_part;
SET search_path TO pg18_vacuum_part;
CREATE TABLE vac_analyze_only (a int);
SELECT create_distributed_table('vac_analyze_only', 'a');
INSERT INTO vac_analyze_only VALUES (1), (2), (3);
-- ANALYZE (no ONLY) should recurse into shard placements
ANALYZE vac_analyze_only;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part;
SELECT max(last_analyze) AS analyze_before_only
FROM pg_stat_all_tables
WHERE relname LIKE 'vac_analyze_only_%'
SELECT coalesce(max(last_analyze), 'epoch'::timestamptz) AS analyze_before_only
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part'
AND relname LIKE 'vac_analyze_only_%'
\gset
\c - - - :master_port
SET search_path TO pg18_vacuum_part;
-- ANALYZE ONLY should not recurse into shard placements
ANALYZE ONLY vac_analyze_only;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part;
SELECT max(last_analyze) = :'analyze_before_only' AS analyze_only_skipped
FROM pg_stat_all_tables
WHERE relname LIKE 'vac_analyze_only_%';
SELECT max(last_analyze) = :'analyze_before_only'::timestamptz
AS analyze_only_skipped
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part'
AND relname LIKE 'vac_analyze_only_%';
\c - - - :master_port
SET search_path TO pg18_vacuum_part;
-- VACUUM (no ONLY) should recurse into shard placements
VACUUM vac_analyze_only;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part;
SELECT max(last_vacuum) AS vacuum_before_only
FROM pg_stat_all_tables
WHERE relname LIKE 'vac_analyze_only_%'
SELECT coalesce(max(last_vacuum), 'epoch'::timestamptz) AS vacuum_before_only
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part'
AND relname LIKE 'vac_analyze_only_%'
\gset
\c - - - :master_port
SET search_path TO pg18_vacuum_part;
-- VACUUM ONLY should not recurse into shard placements
VACUUM ONLY vac_analyze_only;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part;
SELECT max(last_vacuum) = :'vacuum_before_only' AS vacuum_only_skipped
FROM pg_stat_all_tables
WHERE relname LIKE 'vac_analyze_only_%';
SELECT max(last_vacuum) = :'vacuum_before_only'::timestamptz
AS vacuum_only_skipped
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part'
AND relname LIKE 'vac_analyze_only_%';
\c - - - :master_port
SET search_path TO pg18_vacuum_part;
DROP SCHEMA pg18_vacuum_part CASCADE;
SET search_path TO pg18_nn;
-- END PG18 Feature: VACUUM/ANALYZE recurse into inheritance children by default
-- END PG18 Feature: VACUUM/ANALYZE support ONLY to limit processing to the parent
-- PG18 Feature: VACUUM/ANALYZE ONLY on a partitioned distributed table
-- Ensure Citus does not recurse into shard placements when ONLY is used
-- on the partitioned parent.
-- PG18 commit: https://github.com/postgres/postgres/commit/62ddf7ee9
CREATE SCHEMA pg18_vacuum_part_dist;
SET search_path TO pg18_vacuum_part_dist;
SET citus.shard_count = 2;
SET citus.shard_replication_factor = 1;
CREATE TABLE part_dist (id int, v int) PARTITION BY RANGE (id);
CREATE TABLE part_dist_1 PARTITION OF part_dist FOR VALUES FROM (1) TO (100);
CREATE TABLE part_dist_2 PARTITION OF part_dist FOR VALUES FROM (100) TO (200);
SELECT create_distributed_table('part_dist', 'id');
INSERT INTO part_dist
SELECT g, g FROM generate_series(1, 199) g;
-- ANALYZE (no ONLY) should recurse into partitions and shard placements
ANALYZE part_dist;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part_dist;
SELECT coalesce(max(last_analyze), 'epoch'::timestamptz) AS analyze_before_only
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part_dist'
AND relname LIKE 'part_dist_%'
\gset
\c - - - :master_port
SET search_path TO pg18_vacuum_part_dist;
-- ANALYZE ONLY should not recurse into shard placements
ANALYZE ONLY part_dist;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part_dist;
SELECT max(last_analyze) = :'analyze_before_only'::timestamptz
AS analyze_only_partitioned_skipped
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part_dist'
AND relname LIKE 'part_dist_%';
\c - - - :master_port
SET search_path TO pg18_vacuum_part_dist;
-- VACUUM (no ONLY) should recurse into partitions and shard placements
VACUUM part_dist;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part_dist;
SELECT coalesce(max(last_vacuum), 'epoch'::timestamptz) AS vacuum_before_only
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part_dist'
AND relname LIKE 'part_dist_%'
\gset
\c - - - :master_port
SET search_path TO pg18_vacuum_part_dist;
-- VACUUM ONLY parent: core warns and does no work; Citus must not
-- propagate to shard placements.
VACUUM ONLY part_dist;
\c - - - :worker_1_port
SET search_path TO pg18_vacuum_part_dist;
SELECT max(last_vacuum) = :'vacuum_before_only'::timestamptz
AS vacuum_only_partitioned_skipped
FROM pg_stat_user_tables
WHERE schemaname = 'pg18_vacuum_part_dist'
AND relname LIKE 'part_dist_%';
\c - - - :master_port
SET search_path TO pg18_vacuum_part_dist;
DROP SCHEMA pg18_vacuum_part_dist CASCADE;
SET search_path TO pg18_nn;
-- END PG18 Feature: VACUUM/ANALYZE ONLY on partitioned distributed table
-- cleanup with minimum verbosity
SET client_min_messages TO ERROR;