【发布时间】:2018-04-19 16:03:41
【问题描述】:
我有两个表users 和products,它们之间的关联是User has many products。我想将产品数量存储在用户表中,并且应该在每次插入或删除时更新。所以我在数据库中为它编写了一个存储过程并触发它来触发它。问题是当我一次插入数千个产品时,它正在执行触发器per row insertion,并且花费了太多时间。
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();
更新
我已添加:
SET CONSTRAINTS update_promotion_products_count DEFERRED;但似乎它没有取得任何进展,因为现在它需要 6100 毫秒,这与以前有点相似。试过
DEFERRABLE INITIALLY DEFERRED,但还是不行。我认为FOR EACH ROW是实际问题。但是当我用FOR EACH STATEMENT尝试它时,它会抛出语句无效错误。-
把上面的程序改写成这样:
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();
但问题是当你有 1000 个用户,每个用户有 10000 个产品时,你重新计算每个用户的计数(即使只是在数据库中插入一个产品)
我使用的是 PostgreSQL 9.6。
【问题讨论】:
-
您使用的是哪个 Postgres 版本?使用 Postgres 10,您可以使用语句级触发器来做到这一点
-
版本为9.6。在问题中更新。
-
@a_horse_with_no_name 有什么想法吗?
-
@Ahmad:您可以编写一个将临时表中的更改排队的行级触发器,以及一个在末尾应用更改的语句级触发器:stackoverflow.com/a/47909709
-
@NickBarnes 很抱歉,但实际上我并不完全理解。如果您可以在答案中写下问题的上下文,那就太好了,这样我就可以更好地与您讨论并将其标记为已接受的答案。
标签: postgresql stored-procedures triggers database-trigger