From 145fd74a57c4c62d875a2d01e24af4078a0efb4e Mon Sep 17 00:00:00 2001 From: Maksym Buz Date: Thu, 26 Mar 2026 16:00:14 +0000 Subject: [PATCH] Clean up old procedure versions after sequential renaming --- postgresql/procedures/01_auditlog_prep.sql | 27 --- postgresql/procedures/02_maintenance.sql | 183 ------------------ .../procedures/03_enable_partitioning.sql | 43 ---- postgresql/procedures/04_monitoring_view.sql | 28 --- 4 files changed, 281 deletions(-) delete mode 100644 postgresql/procedures/01_auditlog_prep.sql delete mode 100644 postgresql/procedures/02_maintenance.sql delete mode 100644 postgresql/procedures/03_enable_partitioning.sql delete mode 100644 postgresql/procedures/04_monitoring_view.sql diff --git a/postgresql/procedures/01_auditlog_prep.sql b/postgresql/procedures/01_auditlog_prep.sql deleted file mode 100644 index b478c0c..0000000 --- a/postgresql/procedures/01_auditlog_prep.sql +++ /dev/null @@ -1,27 +0,0 @@ --- ============================================================================ --- SCRIPT: 01_auditlog_prep.sql --- DESCRIPTION: Modifies the 'auditlog' table Primary Key to include 'clock'. --- This is REQUIRED for range partitioning by 'clock'. --- ============================================================================ - -DO $$ -BEGIN - -- Check if PK needs modification - -- Original PK is typically on (auditid) named 'auditlog_pkey' - IF EXISTS ( - SELECT 1 FROM pg_constraint - WHERE conname = 'auditlog_pkey' - AND conrelid = 'auditlog'::regclass - ) THEN - -- Verify if 'clock' is already in PK (basic check) - -- Realistically, if 'auditlog_pkey' exists on default Zabbix, it's just (auditid). - - RAISE NOTICE 'Dropping existing Primary Key on auditlog...'; - ALTER TABLE auditlog DROP CONSTRAINT auditlog_pkey; - - RAISE NOTICE 'Creating new Primary Key on auditlog (auditid, clock)...'; - ALTER TABLE auditlog ADD PRIMARY KEY (auditid, clock); - ELSE - RAISE NOTICE 'Constraint auditlog_pkey not found. Skipping or already modified.'; - END IF; -END $$; diff --git a/postgresql/procedures/02_maintenance.sql b/postgresql/procedures/02_maintenance.sql deleted file mode 100644 index c79fb1e..0000000 --- a/postgresql/procedures/02_maintenance.sql +++ /dev/null @@ -1,183 +0,0 @@ --- ============================================================================ --- SCRIPT: 02_maintenance.sql --- DESCRIPTION: Core functions for Zabbix partitioning (Create, Drop, Maintain). --- ============================================================================ - --- Function to check if a partition exists -CREATE OR REPLACE FUNCTION partitions.partition_exists(p_partition_name text) -RETURNS boolean AS $$ -BEGIN - RETURN EXISTS ( - SELECT 1 FROM pg_class c - JOIN pg_namespace n ON n.oid = c.relnamespace - WHERE c.relname = p_partition_name - AND n.nspname = 'public' - ); -END; -$$ LANGUAGE plpgsql; - --- Function to create a partition -CREATE OR REPLACE PROCEDURE partitions.create_partition( - p_parent_table text, - p_start_time timestamp with time zone, - p_end_time timestamp with time zone, - p_period text -) LANGUAGE plpgsql AS $$ -DECLARE - v_partition_name text; - v_start_ts bigint; - v_end_ts bigint; - v_suffix text; -BEGIN - v_start_ts := extract(epoch from p_start_time)::bigint; - v_end_ts := extract(epoch from p_end_time)::bigint; - - IF p_period = 'month' THEN - v_suffix := to_char(p_start_time, 'YYYYMM'); - ELSE - v_suffix := to_char(p_start_time, 'YYYYMMDD'); - END IF; - - v_partition_name := p_parent_table || '_p' || v_suffix; - - IF NOT partitions.partition_exists(v_partition_name) THEN - EXECUTE format( - 'CREATE TABLE public.%I PARTITION OF public.%I FOR VALUES FROM (%s) TO (%s)', - v_partition_name, p_parent_table, v_start_ts, v_end_ts - ); - END IF; -END; -$$; - --- Function to drop old partitions -CREATE OR REPLACE PROCEDURE partitions.drop_old_partitions( - p_parent_table text, - p_retention interval, - p_period text -) LANGUAGE plpgsql AS $$ -DECLARE - v_cutoff_ts bigint; - v_partition record; - v_partition_date timestamp with time zone; - v_suffix text; -BEGIN - -- Calculate cutoff timestamp - v_cutoff_ts := extract(epoch from (now() - p_retention))::bigint; - - FOR v_partition IN - SELECT - child.relname AS partition_name - FROM pg_inherits - JOIN pg_class parent ON pg_inherits.inhparent = parent.oid - JOIN pg_class child ON pg_inherits.inhrelid = child.oid - WHERE parent.relname = p_parent_table - LOOP - -- Parse partition suffix to determine age - -- Format: parent_pYYYYMM or parent_pYYYYMMDD - v_suffix := substring(v_partition.partition_name from length(p_parent_table) + 3); - - BEGIN - IF length(v_suffix) = 6 THEN -- YYYYMM - v_partition_date := to_timestamp(v_suffix || '01', 'YYYYMMDD'); - -- For monthly, we check if the END of the month is older than retention? - -- Or just strict retention. - -- To be safe, adding 1 month to check vs cutoff. - IF extract(epoch from (v_partition_date + '1 month'::interval)) < v_cutoff_ts THEN - RAISE NOTICE 'Dropping old partition %', v_partition.partition_name; - EXECUTE format('DROP TABLE public.%I', v_partition.partition_name); - END IF; - ELSIF length(v_suffix) = 8 THEN -- YYYYMMDD - v_partition_date := to_timestamp(v_suffix, 'YYYYMMDD'); - IF extract(epoch from (v_partition_date + '1 day'::interval)) < v_cutoff_ts THEN - RAISE NOTICE 'Dropping old partition %', v_partition.partition_name; - EXECUTE format('DROP TABLE public.%I', v_partition.partition_name); - END IF; - END IF; - EXCEPTION WHEN OTHERS THEN - -- Ignore parsing errors for non-standard partitions - NULL; - END; - END LOOP; -END; -$$; - --- MAIN Procedure to maintain a single table -CREATE OR REPLACE PROCEDURE partitions.maintain_table( - p_table_name text, - p_period text, - p_keep_history interval, - p_future_partitions integer DEFAULT 5 -) LANGUAGE plpgsql AS $$ -DECLARE - v_start_time timestamp with time zone; - v_period_interval interval; - i integer; - v_past_iterations integer; -BEGIN - IF p_period = 'day' THEN - v_period_interval := '1 day'::interval; - v_start_time := date_trunc('day', now()); - -- Calculate how many past days cover the retention period - v_past_iterations := extract(day from p_keep_history)::integer; - -- Safety cap or ensure minimum? default 7 if null? - IF v_past_iterations IS NULL THEN v_past_iterations := 7; END IF; - - ELSIF p_period = 'week' THEN - v_period_interval := '1 week'::interval; - v_start_time := date_trunc('week', now()); - v_past_iterations := (extract(day from p_keep_history) / 7)::integer; - - ELSIF p_period = 'month' THEN - v_period_interval := '1 month'::interval; - v_start_time := date_trunc('month', now()); - -- Approximate months - v_past_iterations := (extract(year from p_keep_history) * 12 + extract(month from p_keep_history))::integer; - -- Fallback if interval is just days (e.g. '365 days') - IF v_past_iterations = 0 THEN - v_past_iterations := (extract(day from p_keep_history) / 30)::integer; - END IF; - ELSE - RETURN; - END IF; - - -- 1. Create Future Partitions (Current + Buffer) - FOR i IN 0..p_future_partitions LOOP - CALL partitions.create_partition( - p_table_name, - v_start_time + (i * v_period_interval), - v_start_time + ((i + 1) * v_period_interval), - p_period - ); - END LOOP; - - -- 2. Create Past Partitions (Covering retention period) - IF v_past_iterations > 0 THEN - FOR i IN 1..v_past_iterations LOOP - CALL partitions.create_partition( - p_table_name, - v_start_time - (i * v_period_interval), - v_start_time - ((i - 1) * v_period_interval), - p_period - ); - END LOOP; - END IF; - - -- 3. Drop Old Partitions - CALL partitions.drop_old_partitions(p_table_name, p_keep_history, p_period); - - -- 4. Update Metadata - UPDATE partitions.config SET last_updated = now() WHERE table_name = p_table_name; -END; -$$; - --- Global Maintenance Procedure -CREATE OR REPLACE PROCEDURE partitions.run_maintenance() -LANGUAGE plpgsql AS $$ -DECLARE - v_row record; -BEGIN - FOR v_row IN SELECT * FROM partitions.config LOOP - CALL partitions.maintain_table(v_row.table_name, v_row.period, v_row.keep_history, v_row.future_partitions); - END LOOP; -END; -$$; diff --git a/postgresql/procedures/03_enable_partitioning.sql b/postgresql/procedures/03_enable_partitioning.sql deleted file mode 100644 index cd6147b..0000000 --- a/postgresql/procedures/03_enable_partitioning.sql +++ /dev/null @@ -1,43 +0,0 @@ --- ============================================================================ --- SCRIPT: 03_enable_partitioning.sql --- DESCRIPTION: Converts standard Zabbix tables to Partitioned tables. --- WARNING: This renames existing tables to *_old. --- ============================================================================ - -DO $$ -DECLARE - v_row record; - v_table text; - v_old_table text; - v_pk_sql text; -BEGIN - FOR v_row IN SELECT * FROM partitions.config LOOP - v_table := v_row.table_name; - v_old_table := v_table || '_old'; - - -- Check if table exists and is NOT already partitioned - IF EXISTS (SELECT 1 FROM pg_class WHERE relname = v_table AND relkind = 'r') THEN - RAISE NOTICE 'Converting table % to partitioned table...', v_table; - - -- 1. Rename existing table - EXECUTE format('ALTER TABLE public.%I RENAME TO %I', v_table, v_old_table); - - -- 2. Create new partitioned table (copying structure) - EXECUTE format('CREATE TABLE public.%I (LIKE public.%I INCLUDING ALL) PARTITION BY RANGE (clock)', v_table, v_old_table); - - -- 3. Create initial partitions - RAISE NOTICE 'Creating initial partitions for %...', v_table; - CALL partitions.maintain_table(v_table, v_row.period, v_row.keep_history, v_row.future_partitions); - - -- Optional: Migrate existing data - -- EXECUTE format('INSERT INTO public.%I SELECT * FROM public.%I', v_table, v_old_table); - - ELSIF EXISTS (SELECT 1 FROM pg_class WHERE relname = v_table AND relkind = 'p') THEN - RAISE NOTICE 'Table % is already partitioned. Skipping conversion.', v_table; - -- Just run maintenance to ensure partitions exist - CALL partitions.run_maintenance(); - ELSE - RAISE WARNING 'Table % not found!', v_table; - END IF; - END LOOP; -END $$; diff --git a/postgresql/procedures/04_monitoring_view.sql b/postgresql/procedures/04_monitoring_view.sql deleted file mode 100644 index 80139f1..0000000 --- a/postgresql/procedures/04_monitoring_view.sql +++ /dev/null @@ -1,28 +0,0 @@ --- ============================================================================ --- SCRIPT: 04_monitoring_view.sql --- DESCRIPTION: Creates a view to monitor partition status and sizes. --- ============================================================================ - -CREATE OR REPLACE VIEW partitions.monitoring AS -SELECT - parent.relname AS parent_table, - c.table_name, - c.period, - c.keep_history, - count(child.relname) AS partition_count, - count(child.relname) FILTER ( - WHERE - (c.period = 'day' AND child.relname > (parent.relname || '_p' || to_char(now(), 'YYYYMMDD'))) - OR - (c.period = 'month' AND child.relname > (parent.relname || '_p' || to_char(now(), 'YYYYMM'))) - ) AS future_partitions, - pg_size_pretty(sum(pg_total_relation_size(child.oid))) AS total_size, - min(child.relname) AS oldest_partition, - max(child.relname) AS newest_partition, - c.last_updated -FROM partitions.config c -JOIN pg_class parent ON parent.relname = c.table_name -LEFT JOIN pg_inherits ON pg_inherits.inhparent = parent.oid -LEFT JOIN pg_class child ON pg_inherits.inhrelid = child.oid -WHERE parent.relkind = 'p' -- Only partitioned tables -GROUP BY parent.relname, c.table_name, c.period, c.keep_history, c.last_updated;