i have two tables users
and products
and the association between them is that User has many products
. I want to store the count of products in the users table and it should be updated at every insert or delete. So i have written a stored procedure in the database for it and trigger to fire it. The problem is when i am inserting thousands of products at once it is executing the trigger per row insertion
and it is taking too much time.
CREATE FUNCTION update_product_count()
RETURNS trigger AS $$
BEGIN
IF TG_OP = 'DELETE' THEN
UPDATE users SET products_count = products_count - 1 WHERE id = OLD.user_id;
END IF;
IF TG_OP = 'INSERT' THEN
UPDATE users SET products_count = products_count + 1 WHERE id = NEW.user_id;
END IF;
RETURN NULL;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_user_products_count
AFTER INSERT OR UPDATE OR DELETE ON products
FOR EACH ROW EXECUTE PROCEDURE update_product_count();
UPDATE
i have added:
SET CONSTRAINTS update_promotion_products_count DEFERRED;
but seems like it is not making any progress because right now it is taking 6100ms which is somewhat similar to before.Tried
DEFERRABLE INITIALLY DEFERRED
but it is still not working. I thinkFOR EACH ROW
is the actual issue. But when i tried it withFOR EACH STATEMENT
it throws statement invalid error.Rewrote the above procedure like this:
CREATE FUNCTION update_product_count() RETURNS trigger AS $$ BEGIN IF TG_OP = 'DELETE' OR TG_OP = 'INSERT' THEN UPDATE users SET products_count = (SELECT COUNT(1) FROM products WHERE products.user_id = users.id); END IF; RETURN NULL; END; $$ LANGUAGE plpgsql; CREATE TRIGGER update_user_products_count AFTER INSERT OR UPDATE OR DELETE ON products FOR EACH STATEMENT EXECUTE PROCEDURE update_product_count();
But the problem is then when you have 1000 usres with 10000 products each, you recalculate the count of every user (even when just insert a single product in the database)
I'm using PostgreSQL 9.6.