【问题标题】:Plpgsql seems to be deleting and inserting instead of updating - Why?Plpgsql 似乎是删除和插入而不是更新 - 为什么?
【发布时间】:2011-08-27 03:48:38
【问题描述】:

我正在使用 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?

【问题讨论】:

    标签: postgresql plpgsql


    【解决方案1】:

    由于其并发理念,Postgresql 很少使用UPDATE,而且只是最近。你的古董版确实在幕后做了一对DELETE/INSERT

    VACUUMCLUSTER 是保持表格大小可管理的认可方法。 CLUSTER 锁定表(至少在 7.3 中是这样)。您可能希望经常(每天多次)运行普通的VACUUM,并在下班时间运行CLUSTER。当然,这些频率取决于您的更新频率。

    我使用 Postgresql 的经验是向上迁移很容易;转储/恢复每次都是第一次工作。

    【讨论】:

      【解决方案2】:

      7.4 太老了。您确实需要升级到具有良好 autovacuum 并且会自动处理此问题的最新版本。

      不要使用 VACUUM FULL(改用 CLUSTER)。

      【讨论】:

      • 这是遗留系统,我暂时限制在7.4。
      • Postgresql 并没有真正做更新,它会在内部删除/插入它们的位置。这会在数据库中创建死行。定期的旧吸尘器可以回收失去的空间以供重复使用。安排定期真空吸尘器,以便空间可以在没有真空满堵的情况下被回收,而定期真空吸尘器则不会。此外,vacuum full 会为许多访问模式创建索引膨胀,因此您最终会遇到大索引并需要重新索引。最好运行集群(如果 7.4 支持集群)而不是完全真空。
      • 据我了解,CLUSTER(存在于 7.4 上)将提高查询的数据访问速度。我想它可能会提高数据插入(如果表有 pkey)和更新速度。但是,它看起来不会影响这里数据插入速度的主要问题,即死行太多。你能评论一下吗?
      • 另外,如果 CLUSTER 是一个不错的选择,那么它是一次性操作,还是需要定期执行的操作,可能与常规 VACUUM 结合使用?
      • @Scott 您的评论非常有用 - 也许最好作为单独的答案?
      猜你喜欢
      • 1970-01-01
      • 2016-07-14
      • 1970-01-01
      • 2020-08-06
      • 1970-01-01
      • 2021-03-17
      • 2015-10-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多