postgres 触发器创建索引:BEFORE INSERT ON 隐藏一行
postgres trigger creates index: BEFORE INSERT ON hides one row
我有一个调用函数的触发器AFTER INSERT ON mytable
CREATE OR REPLACE FUNCTION myfunction() RETURNS trigger AS
$BODY$
DECLARE
index TEXT;
BEGIN
index := 'myIndex_' || NEW.id2::text;
IF to_regclass(index::cstring) IS NULL THEN
EXECUTE 'CREATE INDEX ' || index || ' ON mytable(id) WITH (FILLFACTOR=100) WHERE id2=' || NEW.id2|| ';';
RAISE NOTICE 'Created new index %',index;
END IF;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
SECURITY DEFINER
COST 100;
ALTER FUNCTION myfunction()
OWNER TO theadmin;
效果很好。对于每个不同的 id2
我创建一个索引。大大加快了相关查询的速度。
如上所述,我触发了这个AFTER INSERT ON
。然而,在这样做之前,我将触发器设置为 BEFORE INSERT ON
。这个函数做了一些奇怪的事情。 (是的,我已经将 RETURN NULL
更改为 RETURN NEW
)
- 插入新行
insert into mytable VALUES(1391, 868, 0.5, 0.5);
- 创建相应的索引
myIndex_868
- 在执行 select 时,插入的行 没有出现在我的 table 中 :(
- 尝试插入同一行会导致
ERROR: duplicate key value violates unique constraint "mytable_pkey"
,因为当然 DETAIL: Key (id, id2)=(1391, 868) already exists.
- 为相同的 id2 插入其他行按预期工作:)
DELETE FROM mytable WHERE id = 1391 and id2 = 868
什么都不做
DROP INDEX myIndex_868;
删除索引。 table 中从未出现的初始行突然出现了!
为什么 BEFORE INSERT ON
表现如此不同?这是 postgres 9.4 中的错误还是我忽略了什么?
为了完整起见:
CREATE TRIGGER mytrigger
AFTER INSERT ON mytable
FOR EACH ROW EXECUTE PROCEDURE myfunction();
对比
CREATE TRIGGER mytrigger
BEFORE INSERT ON mytable
FOR EACH ROW EXECUTE PROCEDURE myfunction();
我认为这是 PostgreSQL 中的错误。我可以用 9.6 重现它。
很明显,该行不包含在索引中,因为它是在 BEFORE
触发器中创建的,但是在我看来,插入行时索引没有更新是一个错误.
我有written to pgsql-hackers征求意见
但除此之外,我看不出整个练习的意义所在。
比创建大量索引更好的方法是创建一个索引:
CREATE INDEX ON mytable(id2, id);
我有一个调用函数的触发器AFTER INSERT ON mytable
CREATE OR REPLACE FUNCTION myfunction() RETURNS trigger AS
$BODY$
DECLARE
index TEXT;
BEGIN
index := 'myIndex_' || NEW.id2::text;
IF to_regclass(index::cstring) IS NULL THEN
EXECUTE 'CREATE INDEX ' || index || ' ON mytable(id) WITH (FILLFACTOR=100) WHERE id2=' || NEW.id2|| ';';
RAISE NOTICE 'Created new index %',index;
END IF;
RETURN NULL;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
SECURITY DEFINER
COST 100;
ALTER FUNCTION myfunction()
OWNER TO theadmin;
效果很好。对于每个不同的 id2
我创建一个索引。大大加快了相关查询的速度。
如上所述,我触发了这个AFTER INSERT ON
。然而,在这样做之前,我将触发器设置为 BEFORE INSERT ON
。这个函数做了一些奇怪的事情。 (是的,我已经将 RETURN NULL
更改为 RETURN NEW
)
- 插入新行
insert into mytable VALUES(1391, 868, 0.5, 0.5);
- 创建相应的索引
myIndex_868
- 在执行 select 时,插入的行 没有出现在我的 table 中 :(
- 尝试插入同一行会导致
ERROR: duplicate key value violates unique constraint "mytable_pkey"
,因为当然DETAIL: Key (id, id2)=(1391, 868) already exists.
- 为相同的 id2 插入其他行按预期工作:)
DELETE FROM mytable WHERE id = 1391 and id2 = 868
什么都不做DROP INDEX myIndex_868;
删除索引。 table 中从未出现的初始行突然出现了!
为什么 BEFORE INSERT ON
表现如此不同?这是 postgres 9.4 中的错误还是我忽略了什么?
为了完整起见:
CREATE TRIGGER mytrigger
AFTER INSERT ON mytable
FOR EACH ROW EXECUTE PROCEDURE myfunction();
对比
CREATE TRIGGER mytrigger
BEFORE INSERT ON mytable
FOR EACH ROW EXECUTE PROCEDURE myfunction();
我认为这是 PostgreSQL 中的错误。我可以用 9.6 重现它。
很明显,该行不包含在索引中,因为它是在 BEFORE
触发器中创建的,但是在我看来,插入行时索引没有更新是一个错误.
我有written to pgsql-hackers征求意见
但除此之外,我看不出整个练习的意义所在。 比创建大量索引更好的方法是创建一个索引:
CREATE INDEX ON mytable(id2, id);