是否可以在postgresql中为每个主键创建索引?

时间:2016-10-19 14:53:33

标签: sql postgresql

考虑我有一个表,其中插入通常有两个字段:

user_id uuid,
date timestamp

我也有一个普通的b树索引(user_id,date)。

这种方法的问题是不能通过postgres并行地对不同的user_id进行插入,因为索引必须按顺序更新,因为它是一棵树,每次插入后都可以重新平衡,所以它必须等到每个特定的插入完成。

我想要的是每个user_id的独立索引,以便插入可以并行完成。有办法吗?

-------编辑:Laurenz Albe的完美答案在下面

1 个答案:

答案 0 :(得分:6)

<强>摘要:

你低估了B树索引的力量。

B树索引上的多个插入可以并行运行,树永远不会重新平衡。相反,您偶尔会有一个索引页面拆分,只会在一段时间内阻止该页面上的操作。

<强>参考文献:

分页的算法在Lehman and Yao的着名论文中描述(对索引内部感兴趣的人必读),PostgreSQL源代码中的nbtree README描述了删除的更多细节。处理完毕。

插入算法的简短说明:

只要索引页面未满,就会插入新条目。这只会导致索引页面的短暂锁定。

如果页面已满,则使用Lehman&amp; amp; Yao算法,一次最多锁定三页。此拆分需要在父页面中新创建的页面的新条目,因此该页面可能也必须拆分,可能会重复到根页面。

仍然需要不超过三个锁,因为这些操作是一个接一个地发生的。

请注意,这样的根页面拆分在索引的生命周期中仅发生3-4次,因为很少有索引超过5个级别。

这样,B树索引的所有分支都具有相同的深度,因此索引始终是平衡的,不需要重新平衡。重新平衡只能在删除条目时很有意思,但PostgreSQL不会这样做(除非它在完全为空时回收索引页)。

有关您问题的其他说明:

使用像您建议的多个索引不会更快 - 如果您必须为每个user_id创建索引,这会使事情变得更加复杂和缓慢,并且这些索引不能用于无论如何都要搜索。

尽管如此,索引可以缓慢地降低插入速度。如果同时插入和查询数据,这是一个无法避免的问题。如果在您进行批量插入时没有人查询数据,您可以删除索引并在之后重新创建它。