-- -- Reduced generation of dead tuples in postgres. -- -- Background: In the old version, the fields latest and live -- revisions were updated always via two separate DML statements. -- Every update causes in PostgreSQL (tested against pg 9.6) one more -- dead tuple, such that on busy systems, we see 30k + dead tuples per -- hour. These dead tuples in turn cause more auto vacuum operations -- and can lead to abandoned query plans. -- -- This change can reduce the number of dead tuples on cr_items into -- half, by allowing both fields to be set in one operation (namely -- content_item__set_live_revision). This function has an optional 4th -- argument that can cause this optimization. For legacy applications, -- nothing changes. -- -- Btw: since all commonly used applications use the live revision, the -- fallback of the latest_revision is unused. One can consider to -- remove the cr_revision_latest_tr, at least on on certain -- installations. -- -- GN DROP FUNCTION IF EXISTS content_item__set_live_revision(integer, character varying, timestamp with time zone); select define_function_args('content_item__set_live_revision','revision_id,publish_status;ready,publish_date;now(),is_latest;f'); -- -- procedure content_item__set_live_revision/1..4 -- CREATE OR REPLACE FUNCTION content_item__set_live_revision( p__revision_id integer, p__publish_status varchar default 'ready', p__publish_date timestamptz default now(), p__is_latest boolean default false ) RETURNS integer AS $$ DECLARE BEGIN if p__is_latest then update cr_items set live_revision = p__revision_id, publish_status = p__publish_status, latest_revision = p__revision_id where item_id = (select item_id from cr_revisions where revision_id = p__revision_id); else update cr_items set live_revision = p__revision_id, publish_status = p__publish_status where item_id = (select item_id from cr_revisions where revision_id = p__revision_id); end if; update cr_revisions set publish_date = p__publish_date where revision_id = p__revision_id; return 0; END; $$ LANGUAGE plpgsql; -- -- Trigger to maintain latest_revision in cr_items -- CREATE OR REPLACE FUNCTION cr_revision_latest_tr () RETURNS trigger AS $$ DECLARE v_latest_revision cr_revisions.revision_id%TYPE; BEGIN select latest_revision from cr_items into v_latest_revision where item_id = new.item_id; if v_latest_revision <> new.revision_id then update cr_items set latest_revision = new.revision_id where item_id = new.item_id; end if; return new; END; $$ LANGUAGE plpgsql;