PostgreSQL 上所有列的索引

Posted

技术标签:

【中文标题】PostgreSQL 上所有列的索引【英文标题】:Index of all columns on PostgreSQL 【发布时间】:2014-12-14 15:18:04 【问题描述】:

这是我现在的情况:

我有一个(主)表,其中有一个 id 和几列。 然后还有 3 个表只包含一个 id(连接到主表的 id)和一个 timestamp

所有表上的 id 都被定义为唯一的,因此id 有一个隐式索引,可以加快 JOIN。问题是,如果我在加入后检索timestamp,它不在索引中,因此它强制 Postgres 进行位图索引扫描和位图堆扫描(或 seq 扫描,取决于行数),仅适用于那个值。

问题是,我应该将隐式索引替换为同时包含 id 和时间戳的索引吗?那将是一个与表具有相同数据的索引,在这方面听起来很浪费空间。

另外,如果我希望 UNIQUE 检查保持原位,我认为我必须保留原始索引。

更新:忘了补充,这些表具有非常高的恒定写入率和零星读取,但读取一次访问很多行。这就是为什么我宁愿使用所有插入而不是就地更新(全部在一张表中)。 另一件事是,这些表中的行可能以任何顺序出现,我无法确保主表行将在小行到达之前插入。

【问题讨论】:

您必须确实保留原始索引才能保留约束; Pg 没有仅在某些列上唯一的 btree 索引。至于其余的 - 这只是一个权衡,真的。 【参考方案1】:

您的表在id 上具有UNIQUE 约束,并且只有一个其他列。 idmain_table.id 相连,这也是独一无二的,因此是有效的 1:1 关系。

您还担心索引会浪费空间吗?

我建议您将这些表全部替换为主表中的单个可空列。这将节省更多空间并自动保证主表中每个id 一个值。

与其他表格相比,不要太担心NULL storage, that's extremely cheap。

如果主表很大,而辅助表只有很少的行(比率 (id) 上的 UNIQUE 或 PK 约束的(隐式)索引除了(id, timestamp) 上的多列索引以允许仅索引扫描。

【讨论】:

确实,我使用视图将这些表转换为一个带有 NULL 的表。我在写作时不这样做的原因是因为这些表的写入率非常高,并且非主行可能在主行之前到达。出于这些原因,我选择仅插入以避免更新和 mysql 具有但 Postgres 缺乏的整个插入或更新逻辑 @ArielFlesler:我明白了,这些都是很好的理由。有针对 UPSERT (MERGE) here 或 here 的解决方案,但无论哪种方式,在小型辅助表中更新都更便宜。所以我的最后一章就是答案:你需要 both 索引。

以上是关于PostgreSQL 上所有列的索引的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL中如何查询索引的元数据

如何列出为 postgres 中的表创建的索引

如何在 Postgres 中的 JSON 字段上创建索引?

postgres 空间索引

PostgreSQL 可以索引数组列吗?

Postgres 索引未使用正确的计划