如何通过更新来避免碎片化的数据库存储?

时间:2011-03-14 15:58:09

标签: postgresql

当我有下表时:

CREATE TABLE test
(
  "id" integer NOT NULL,
  "myval" text NOT NULL,
  CONSTRAINT "test-id-pkey" PRIMARY KEY ("id")
)

执行以下许多查询时:

UPDATE "test" set "myval" = "myval" || 'foobar' where "id" = 12345

然后行myval将随着时间的推移变得越来越大。 postgresql会做什么?从哪里获得空间?

我可以避免postgresql需要多个人寻求阅读特定的myval列吗?

postgresql会自动执行此操作吗?

我知道通常我应该尝试更多地规范化数据。但我需要用一次寻找来读取价值。每次更新(添加数据)时,Myval将放大约20个字节。一些列将有1-2个更新,大约1000个更新。 通常我会使用一个新行而不是更新。但随后选择变慢。 所以我想到了非规范化的想法。

2 个答案:

答案 0 :(得分:4)

更改表的FILLFACTOR以为将来的更新创建空间。这也可以是HOT更新,因为文本字段没有索引,以使更新更快并且autovacuum开销更低,因为HOT更新使用微虚拟。 CREATE TABLE语句包含有关FILLFACTOR的一些信息。

ALTER TABLE test SET (fillfactor = 70);
-- do a table rebuild to blow some space in your current table:
VACUUM FULL ANALYZE test;
-- start testing

值70不是完美的设置,它取决于您的独特情况。也许你90岁就可以了,也可能是40岁或者别的什么。

答案 1 :(得分:1)

这与TEXT in PostgreSQL的这个问题有关,或者至少答案是相似的。 PostgreSQL stores large columns远离主表存储:

  

非常长的值也存储在后台表中,这样它们就不会干扰对较短列值的快速访问。

因此,您可以预期TEXT(或BYTEA或大VARCHAR)列始终远离主表存储,SELECT id, myval FROM test WHERE id = 12345之类的内容将需要两次搜索将两列从磁盘上拉下来(更多的是寻求解决它们的位置)。

如果您的更新确实导致您的SELECT速度变慢,那么您可能需要查看vacuuming策略。