Plpgsql似乎是删除和插入而不是更新 - 为什么?

时间:2011-05-17 11:06:20

标签: postgresql plpgsql

我正在使用postgreSQL 7.4。

我有一张大桌子,称之为table_a:

key1 INT NOT NULL, 
key2 INT NOT NULL, 
data INT NOT NULL, 
itstamp INT NOT NULL DEFAULT (date_part('EPOCH'::text, (timeofday())::timestamp without time zone))::INTEGER

和一个汇总key1最后更新时间的表,称之为table_b:

key1        INT NOT NULL,
max_itstamp INT NOT NULL

我在plpgsql中创建了一个触发器函数,以根据需要更新或插入table_b中的行:

CREATE OR REPLACE FUNCTION table_b_update() RETURNS TRIGGER AS '
 DECLARE
  l_key1 INT;
  l_itstamp INT;
 BEGIN
  l_key1 := new.key1;
  l_itstamp := new.itstamp;
  PERFORM TRUE FROM table_b WHERE key1=l_key1;
  IF NOT FOUND THEN 
   INSERT INTO table_b(key1, max_itstamp) values (l_key1, l_itstamp);
  ELSE
   UPDATE table_b SET max_itstamp=l_itstamp WHERE key1=l_key1;
  END IF;
  RETURN NULL;
 END'
LANGUAGE plpgsql IMMUTABLE;

然后我将一个触发器附加到table_a:

CREATE TRIGGER table_a_trigger1 AFTER INSERT OR UPDATE ON table_a FOR EACH ROW
EXECUTE PROCEDURE table_b_upate();

现在,将新数据插入table_a的时间逐渐增加。 table_b的文件占用空间稳步增长。

我在函数中使用了RAISE NOTICE命令来确认If语句在第一次调用每个键后导致UPDATE而不是INSERT。

由于每个INSERT的插入时间都在增长,我在table_b上尝试了一个VACUUM FULL。插入时间更改回早期插入的大致时间。 table_b的文件大小大大减少了。在VACUUM FULL之后,插入时间开始再次增长。我不想在每次INSERT后都执行VACUUM FULL。

UPDATE是否可能在table_b中实际执行DELETE和INSERT?

2 个答案:

答案 0 :(得分:1)

由于它的并发性哲学,Postgresql很少有UPDATE到位,而且最近才有。{1}}。你的古董版确实在幕后做了DELETE/INSERT对。

VACUUMCLUSTER是经过批准的方法,可以保持表格大小的可管理性。 CLUSTER锁定表(至少,它在7.3中)。您可能希望在非工作时间内经常运行普通VACUUM(每天多次)和CLUSTER。当然,这些频率取决于您的更新频率。

我对Postgresql的体验是向上迁移很容易; dump / restore每次都是第一次工作。

答案 1 :(得分:0)

7.4非常古老。你真的需要升级到一个具有良好autovacuum的最新版本,并将自动处理。

请勿使用VACUUM FULL(请尝试使用CLUSTER)。