I am trying to emulate MERGE
behavior with pl/pgsql:
-- Generate the data from funtion
CREATE TEMP TABLE temp_x (id int, id2 int, data text, created_at timestamp, updated_at timestamp) ON COMMIT DROP;
INSERT INTO temp_x SELECT * FROM set_gernating_function(p);
-- DELETE record with same id2
DELETE FROM x WHERE NOT EXISTS (SELECT 1 FROM temp_x WHERE temp_x.id=x.id) AND id2=p.id2;
-- UPSERT by (id, id2)
INSERT INTO x
SELECT * FROM temp_x z
ON CONFLICT(id, id2) DO UPDATE
SET
updated_at=excluded.updated_at,
data=excluded.data;
But the temp table usage is generating bloat in pg_class
and pg_attr
table very fast -- Faster then I could do vacuum -- and affect other queries. Any idea?
There are some restrictions:
- Preserve the
created_at
time if the id already exist - x have a delete-trigger, so no unnecessary delete.
- The
set_generating_function
is slow - The size for temp_x is small. (< 50)
- The run rate is very high (thousands per second)
AND id2=p.id
refers to an aliasp
that is not present. Should that be part of the co-related sub-query?p
is a custom type from function parameter. Should be irrelevance here.