Postgresql Hstore和Toast Bloat

时间:2014-05-17 05:49:09

标签: postgresql hstore postgresql-9.3

我使用hstore,Postgresql 9.3.4来存储每个事件在某一天发生的计数,并进行如下更新。

days_count = days_count || hstore('x', (coalesce((days_count -> 'x')::integer, 0) + 1)::text)

其中x是一年中的某一天。在运行模拟生产的预期行为后,我最终得到一张 150MB + 2GB吐司+ 25-30MB的表格,分析和真空之后。

我现在将上面的列拆分为每月一列,如下所示

y_month_days_count = y_month_days_count || hstore('x', (coalesce((y_month_days_count -> 'x')::integer, 0) + 1)::text)

其中x是月中的某天,y是一年中的月份。 我现在仍在运行模拟,但到目前为止,在第三步完成时,我的速度为60MB +相当稳定的20-30MB Toast + 25-30MB的索引。这意味着最终我应该在Analyze and Vacuum之后以 180MB + 30-40MB for Toast + 25MB-30MB for index 结束。

首先,Hstore和Toast膨胀有什么已知的问题可以解释我第一次设置的问题吗?

第二,我现在解决这些列的解决方案会因为一个表上的hstore列数量而导致hstore和性能出现任何类型的问题吗?现在看起来很稳定,行数达到数十万,虽然我知道更多的列可以让事情变慢,但我不确定hstore列是否会更糟。

最后我确实找到了一些东西。我有一个hstore列,最终代表每天每小时,所以它有24个不同的键。当我为这一列运行模拟时,我最终几乎没有吐司,在KB中,但是当我运行整个模拟时,日期分为几个列,我最大的hstore有52个键。

因此,对于一个计数器或一两个字的简单存储,在我看到hstore的任意数量的toast之前,最大键数是24到52个键。

1 个答案:

答案 0 :(得分:4)

  

首先,Hstore和Toast膨胀有什么已知问题可以解释我第一次设置的问题吗?

当您更新包含TOASTtexthstore 的外线存储json ed字段的任何部分时,必须重新填写整个字段-written 作为新的行版本。这是MVCC的结果 - 必须保留可能仍然对另一个事务可见的行的每个版本的副本。

当任何正在运行的事务不再需要旧版本时,旧文件可以被vacuum删除,因此在实践中,只要autovacuum运行得足够激烈,影响最小

因此,如果您要更新包含大texthstorejson字段的大量行,或者经常更新它们,请调整autovacuum以使其更频繁地运行并且更快地运行。确保没有长时间运行的<IDLE> in transaction连接。

你说你引用的表格大小是“经过分析和真空”之后但是我猜你只运行了一个普通的vacuum,所以表格膨胀会被PostgreSQL重新使用但不会释放回操作系统。看看VACUUM FULL是否压缩它。

  

由于一个表上的hstore列数量,我目前解析列的解决方案是否会导致hstore和性能出现任何类型的问题?

取决于您的查询模式和工作量,但可能不是。