仅INSERT表的GIN索引的索引膨胀

时间:2019-06-21 13:40:45

标签: postgresql performance heroku indexing

我有一个表,该表的列为hstore数组。在JSON表示法中,该字段的数据如下:

[
  { type: "Pickup", id: "49593034" },
  { type: "User", id: "5903" },
  ...
]

单个记录在数组中的hstore数量可能高达10,000,尽管可能更少。该表仅接收插入。添加记录后,不会删除或更新任何数据。

此表中目前大约有9万条记录,并且通常每天增加几百条。较早记录中的值可能具有与较早记录中的值不同的ID。

我需要能够在此列上进行搜索。例如,我可能想知道此列包含'type=>User,id=>5903'::hstore的所有记录。我发现如果我在此列上创建了GIN索引并使用&&运算符查询,它就能非常快速地搜索此数据。

我遇到了一个问题,该查询的膨胀程度很高。 PG停止使用该索引,并切换到表扫描,导致它非常慢。我通过在索引上运行REINDEX来解决此问题。

我发现肿胀过了一会儿又回来了。尽管它没有再次切换到表扫描(即使膨胀很大),但我担心它会在我再次看到它变高时抢先进行重新索引。每当执行此操作时,都必须使函数脱机,因为重新编制索引会根据文档阻止该索引的使用。

我正在使用Heroku的PG服务,他们提供了一种查询膨胀的工具。可以在here中找到它执行的查询。

执行REINDEX后,索引大小约为1GB。根据Heroku的查询,它膨胀时会增长到11GB左右。

我的问题是:

  1. 究竟是什么导致肿胀?我了解到表DELETEUPDATE会导致膨胀。数据的添加是否导致它不得不重新平衡一棵树或其他导致索引中的页面失效的东西?
  2. Heroku查询中的数据是否准确。我已经阅读了一些关于btree而不是gin索引的膨胀查询的内容。也许这表明一个不存在的问题。它真正停止使用索引的唯一时间是我第一次进行大量插入以填充表时。之后,它膨胀了,但一直使用索引。也许我知道不再有问题,只是无缘无故地抢先索引。
  3. 我是否应该更改架构中的某些内容以免于维护?

我当时正在考虑对其进行重构,以便将该列中的数据存储在单独的表中。这个单独的表会将主表的类型,ID和ID存储为单独的列。我将在typeid字段上创建btree索引。这会给我一个一般免维护的查询吗?我认为这样做也会更快,因为id可以存储为真实数字。目前,它存储为字符串,因为hstore值始终是字符串。

0 个答案:

没有答案