【发布时间】:2015-02-27 10:38:40
【问题描述】:
假设,我的数据库中有 2 个表 (postgresql-9.x)
CREATE TABLE FOLDER (
KEY BIGSERIAL PRIMARY KEY,
PATH TEXT,
NAME TEXT
);
CREATE TABLE FOLDERFILE (
FILEID BIGINT,
PATH TEXT,
PATHKEY BIGINT
);
每当我插入或更新FOLDERFILE 时,我都会自动从FOLDER.KEY 更新FOLDERFILE.PATHKEY:
CREATE OR REPLACE FUNCTION folderfile_fill_pathkey() RETURNS trigger AS $$
DECLARE
pathkey bigint;
changed boolean;
BEGIN
IF tg_op = 'INSERT' THEN
changed := TRUE;
ELSE IF old.FILEID != new.FILEID THEN
changed := TRUE;
END IF;
END IF;
IF changed THEN
SELECT INTO pathkey key FROM FOLDER WHERE PATH = new.path;
IF FOUND THEN
new.pathkey = pathkey;
ELSE
new.pathkey = NULL;
END IF;
END IF;
RETURN new;
END
$$ LANGUAGE plpgsql VOLATILE;
CREATE TRIGGER folderfile_fill_pathkey_trigger AFTER INSERT OR UPDATE
ON FOLDERFILE FOR EACH ROW EXECUTE PROCEDURE fcliplink_fill_pathkey();
所以问题是关于函数folderfile_fill_pathkey() 的波动性。文档说
任何有副作用的函数都必须标记为 VOLATILE
但据我了解——这个函数不会改变它所依赖的表中的任何数据,所以我可以把这个函数标记为IMMUTABLE。对吗?
如果我在同一个事务中将许多行批量插入FOLDERFILE,那么 IMMUTABLE 触发器函数会不会有任何问题,例如:
BEGIN;
INSERT INTO FOLDERFILE ( ... );
...
INSERT INTO FOLDERFILE ( ... );
COMMIT;
【问题讨论】:
-
这个"function"(严格来说是它的主体)不是
IMMUTABLE,它只是STABLE(它从你的FOLDER表中选择,可以改变随着时间的推移:您的函数不保证相同的 "parameters") 结果相同 -- 但是,它是一个触发器,而不是经典函数:函数波动只对查询优化,但只会给你带来麻烦,如果优化触发器,f.ex.STABLE- 不适合AFTER触发器希望查询当前命令修改的行。 -
谢谢@pozs!我实际上并没有完全理解
IMMUTABLE和STABLE之间的区别,所以我现在必须在我的数据库中修复一些东西。因此,非常感谢您的评论。 -
@pozs,据我所知 - 使我的函数
STABLE而不是VOLATILE不会给我任何性能优势?如果你把它作为一个答案也很好,这样我就可以接受它——否则我必须自己做。 -
很难预测,
STABLE是否真的表现更好。查询优化取决于很多事情。 (在你的情况下——即你没有在函数内查询触发器的目标表FOLDERFILE——这无关紧要)。但是,如果您想要精确,您应该使用真实数据测试这两种变体。 -
好的,谢谢,我稍后会做基准测试并在这里发布结果
标签: postgresql immutability volatile volatility